据我了解,
对于诸如列表之类的可变对象,如果基础对象支持诸如列表之类的变异,则+ =(增加的赋值)会导致该对象的变异。当然,这对于不支持__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中的新实例变量栏可能会遮盖类属性。但是我看到这样做f.bar+=4
反过来也会更新class属性,这对我来说完全令人困惑。
有人可以帮我吗?
这可能有点微妙。你可以想到
self.bar += [x]
相当于
self.bar = self.bar.__iadd__([x])
因此,self.bar.__iadd__([x])
对列表进行突变(本质上是调用)list.extend
,然后返回列表对象。此列表对象与引用的对象相同TestClass.bar
,已分配给instance属性。
因此,现在您有了一个实例属性,它的名称与类属性的名称相同,并且都碰巧绑定到了相同的列表对象
甚至在[documentation]中也警告过:
对于作为属性引用的目标,关于类和实例属性的警告同样适用于常规分配。
需要注意的是:
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句