文档给出了以下示例:
class Dog:
tricks = [] # mistaken use of a class variable
def __init__(self, name):
self.name = name
def add_trick(self, trick):
self.tricks.append(trick)
d1 = Dog('Fiddo')
d2 = Dog('Buddy')
d1.add_trick("role over")
d2.add_trick("play dead")
print(d2.tricks)
["role over", "play dead"]
这证明了类变量的糟糕用法,因为我们显然不希望所有狗都使用相同的技巧列表。
但是当我尝试这个时:
class A:
static_attr = 'Static'
def __init__(self):
self.object_attr = 'Objective'
def change_static(self, val):
self.static_attr = val
a1, a2 = A(), A()
a1.change_static("Something")
print(a2.static_attr)
我得到:
Static
为什么对于列表对象,当通过对象修改类变量时,它对所有实例都进行了修改,但对于字符串则没有?
这里有一些东西可以更好地理解它:
class A:
static_attr = 'Static'
def __init__(self):
self.object_attr = 'Objective'
@staticmethod
def change_static(val):
A.static_attr = val
a1, a2 = A(), A()
A.change_static("Something")
print(a2.static_attr)
静态属性对于同一类的每个实例都是通用的。 因此,通过对象而不是类调用此参数可能是问题所在。
在第一种情况下,您尝试访问名为self.tricks
的变量。Python 在实例上找不到它,它在类上寻找它并找到了它。然后,通过追加到列表来操作变量指向的值。
在第二个示例中,您将在具有self.static_attr = val
的实例上创建一个名为self.static_attr
的名称,并为其分配一个值。现在,您有两个static_attr
变量 - 一个在类上,一个在实例上。这称为阴影。
现在,当您尝试访问self.static_attr
并且尚未在实例上定义它的实例将获得类变量时,但已定义它的实例将获取实例变量。这在类文档中有很好的描述
请注意,您仍然可以使用以下内容显式引用类变量:
self.__class__.static_attr
或
A.static_attr