Python中的类变量和实例变量问题

3
当我有这个类时,变量'value'是类变量。
class Hello:
    value = 10
    def __init__(self):
        print 'init'

我有一个对象'h',我可以通过Hello.value和h.value获取相同的值'10'。

h = Hello()
print Hello.value
print h.value

当我运行这个命令时,
h.value = 20

当我运行它们时,我得到值“10”和“20”。
print Hello.value
print h.value

为什么会这样呢?

  • Q1 : 为什么'print h.value'能够输出Hello.value的值,而不是报错?
  • Q2 : h.value = 20是否引入了一个类似于'self.value = 20'的新变量?
  • Q3 : 是否有一种方法可以防止创建实例变量(或防止运行代码'h.value = 20')?
2个回答

4
这是Python中属性查找的工作方式:
  1. 如果在实例的字典中找不到属性,则会在其类的字典中查找,如果在那里也找不到,则会在基类的字典中继续查找。
  2. 如果您将一个实例属性分配给一个实例,则这将仅影响该实例——即如果该实例中已存在该属性,则更新该属性,否则在该实例的字典中创建它。
如果您不喜欢这种行为,可以覆盖__setattr__()方法来执行任何您想要的操作——例如,如果不希望允许实例属性的创建,则抛出错误。后者也可以通过向类添加__slots__=[]来实现。

4
如果Python查找o.attr,它首先检查对象实例,然后是其类,然后是基类,以此类推。这样做既适用于方法又适用于数据属性(即数据属性和代码属性之间没有区别)。
在赋值时,值总是被分配给实例。因此,
  • A1. 因为它会回退到类(否则方法将无法正常工作)

  • A2. 是的,它会。

  • A3. 您可以定义一个引发异常的__setattr__方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接