Python类变量是静态的吗? [英] Is Python class variable static?
问题描述
看到以下代码:
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的class变量独立于每个实例,因为将狗实例的 powers
变量从无权限更改为树皮不会影响cat实例的 powers
变量
it looks like python's class variable is independent to each instance because change dog instance's powers
variable from no power to bark does not affect the cat instance's powers
variable
但是,通过执行以下操作:
However, by doing this:
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变量(这次是列表)是静态的,因为将元素添加到狗实例的 powers
也会影响cat实例的 powers
.
The example shows powers variable (it is a list this time) is static since append an element to dog instance's powers
also affects cat instance's powers
.
我还尝试了通过调用add_power将幂更改为int并将幂增加1的方式,它们彼此之间不会相互影响.因此,我很困惑为什么将元素添加到作为类变量的列表中会影响其他实例.
I also experimented with changing the powers to an int and increment powers by 1 by calling add_power, and they don't affect each other. So I am really confused why appending an element to a list which is a class variable affects other instances.
推荐答案
实例变量名称可以 shadow 相同名称的类变量.
An instance variable name can shadow a class variable of the same name.
>>> 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
{}
并非是class变量是静态的"( A.var
可以通过常规属性访问来修改或删除).相反,发生的是:访问 a.var
首先在实例的名称空间( a .__ dict __
)中尝试名称 var
,如果失败,则查找返回到检入类的名称空间( A .__ dict __
).
It's not the case that the class variable is "static" (A.var
can be modified or deleted via normal attribute access). What's happening instead is: accessing a.var
first tries the name var
in the instance's namespace (a.__dict__
), and if that fails then the lookup falls back to checking in the class's namespace (A.__dict__
).
The reason you don't see the same behaviour when using a list on the class object is that this line is not an assignment statement:
self.powers.append(power)
使用赋值语句将的看似等效的版本会重新创建与您观察到的名称相同的阴影:
A seemingly equivalent version which is using an assignment statement would recreate the same name shadowing that you observed:
self.powers = self.powers + [power] # not actually equivalent!
总结:对于类属性使用整数或字符串时,您是在实例名称空间中创建一个条目(由于赋值语句),但是当使用列表时,您直接对类变量进行操作,这确实是在所有实例之间共享.
In summary: when using an integer or a string for the class attribute you were creating an entry in the instance namespace (because of the assignment statement), but when using a list you act directly on the class variable, which is indeed shared between all instances.
这篇关于Python类变量是静态的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!