Class 变量:"class list" 与 "class boolean"

Class variables: "class list" vs "class boolean"

我不明白以下示例中的区别。一次 class 的实例可以更改另一个实例的 class 变量,而另一次它不能?

示例 1:

class MyClass(object):
    mylist = []

    def add(self):
        self.mylist.append(1)

x = MyClass()
y = MyClass()
x.add()
print "x's mylist: ",x.mylist
print "y's mylist: ",y.mylist

输出:

x's mylist: [1]

y's mylist: [1]

所以这里 class A 的实例 x 能够访问和修改 class 属性 mylist 这也是A.

的实例 y

示例 2:

class MyBank(object):
    crisis = False

    def bankrupt(self) :
        self.crisis = True

bankX = MyBank()
bankY = MyBank()
bankX.bankrupt()
print "bankX's crisis: ",bankX.crisis
print "bankY's crisis: ",bankY.crisis

bankX's crisis: True

bankY's crisis: False

为什么这在这个例子中不起作用?

第一种情况在 add 方法中没有赋值:

def add(self):
    self.mylist.append(1)  # NOT self.mylist = something

在第二种情况下有一个赋值:

def bankrupt(self) :
    self.crisis = True  # self.crisis = something

当在实例上设置属性时,它总是仅在特定实例上设置(它被放入实例的 __dict__ 属性)。 Class __dict__ 不受影响。

在第一种情况下没有分配,因此适用标准查找规则。由于instance的__dict__属性中没有"mylist",所以回退到class__dict__

add 中执行的操作 改变 存储在 MyClass.__dict__ 中的值。这就是为什么在所有情况下都可以观察到变化。

考虑以下片段(它可能更好地解释您的问题):

class MyClass:
    x = []

x1 = MyClass()
x2 = MyClass()
x3 = MyClass()

x1.x.append(1)

print x1.x  # [1]
print x2.x  # [1]
print x3.x  # [1]
assert x1.x is x2.x is x3.x

x3.x = "new"  # now x3.x no longer refers to class attribute

print x1.x # [1]
print x2.x # [1]
print x3.x # "new"
assert x1.x is x3.x  # no longer True!