看到以下代码:
class Super:
powers = 'no power'
def __init__(self, name):
self.name = name
def add_power(self, power):
self.powers = power
dog = Super('dog')
cat = Super('cat')
dog.add_power("bark")
print (dog.powers) # print bark
print (cat.powers) # print no power
看起来python的类变量独立于每个实例,因为更改狗实例的powers
变量从无力到树皮不会影响cat实例的powers
变量
然而,通过这样做:
class Super:
powers = ["no power"]
def __init__(self, name):
self.name = name
def add_power(self, power):
self.powers.append(power)
dog = Super('dog')
cat = Super('cat')
dog.add_power("bark")
print (dog.powers) # print ['no power', 'bark']
print (cat.powers) # print ['no power', 'bark'] # why cat.powers is also affected???
示例显示powers变量(这次是一个列表)是静态的,因为将一个元素附加到dog实例的powers
也会影响cat实例的powers
。
我还尝试将权限更改为int并通过调用add_power将权力增加1,并且它们不会相互影响。所以我真的很困惑为什么将一个元素附加到列表中,这是一个类变量会影响其他实例。
答案 0 :(得分:9)
实例变量名称可以 shadow 具有相同名称的类变量。
>>> class A:
... var = 'class var'
...
>>> a = A()
>>> vars(a) # no instance variables
{}
>>> a.var # attribute lookup resolved at the class level
'class var'
>>> a.var = 'instance var' # create an instance variable
>>> vars(a) # the name `var` now exists in the instance dict
{'var': 'instance var'}
>>> a.var # attribute lookup resolved at the instance level
'instance var'
>>> type(a).var # note: the class variable still exists!
'class var'
>>> del a.var # deletes from the instance dict
>>> a.var # ..but the name `var` remains available at the class level
'class var'
>>> vars(a) # instance dict is again empty
{}
不是类变量是"静态" (A.var
可以通过普通属性访问进行修改或删除)。发生的事情是:访问a.var
首先在实例的命名空间(var
)中尝试名称a.__dict__
,如果失败,则查找将回退到检查班级的命名空间(A.__dict__
)。
在类对象上使用列表时,您没有看到相同的行为的原因是此行不是assignment statement :
self.powers.append(power)
使用赋值语句的看似等效的版本将重新创建您观察到的相同名称阴影:
self.powers = self.powers + [power] # not actually equivalent!
总结:当为类属性使用整数或字符串时,您在实例命名空间中创建了一个条目(因为赋值语句),但是当使用列表时,您直接对类变量执行操作,这确实是在所有实例之间共享。