【发布时间】:2020-04-22 19:40:17
【问题描述】:
据我了解,
对于像列表这样的可变对象,如果底层对象支持像列表一样的突变,+=(增强赋值)会导致对象的突变。当然,这不适用于不支持突变的不可变对象,因为__iadd__ 不存在并且__add__ 是被调用的对象。
考虑以下代码:
class TestClass:
bar = []
def __init__(self, x):
self.bar += [x]
f = TestClass(1)
g = TestClass(2)
h = TestClass(3)
print(f.bar)
print(g.bar)
print(TestClass.bar)
现在,我明白为什么所有三个 g、f、h 都会打印出 [1, 2, 3],因为我们正在“改变”类属性。
但是当我尝试通过 print(f.__dict__) 查看对象的命名空间时,我也看到了对象内部的 bar 属性。
问题 1:如果实际发生变异的属性是类属性,为什么要在对象命名空间中创建实例?
其次,“如果”该实例变量是在对象中创建的(如 f),那么 f.bar += 4 应该只影响对象 f,因为 f 中的新实例变量 bar 应该隐藏了类属性。但我看到这样做f.bar+=4 反过来也会更新类属性,这让我完全困惑。
有人可以帮我解决这个问题吗?
【问题讨论】:
-
不,它没有。它改变了一个实例属性。每次您分配给
self.some_attribute时,它都会分配给一个实例属性。 -
如果它分配给实例属性,那么为什么 f.bar += 4 稍后也会更新类属性?如果它是在对象的上下文中创建的,那么它应该隐藏类属性吗?
-
因为类属性从未重新绑定,而是
self.bar += [x]将同一个对象绑定到实例。所以现在你有一个与类属性同名的实例属性,并且两者都绑定到同一个列表对象
标签: python python-3.x