Python类的组合时产生的属性同步改变问题

Posted poceer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python类的组合时产生的属性同步改变问题相关的知识,希望对你有一定的参考价值。

问题引入:

class A:
    x = 1
class B:
    t = A()

b1 = B()
b2 = B()
b1.t.x = 2
print(b2.t.x)

>>> 2

为什么操作对象b1 会改变另一个对象 b2 的属性值?对象之间的属性应该相互独立?难道类的对象属性和列表一样是一种可变属性,操作对象属性会改变类属性,从而改变了另一个该类实例中的属性?

 

print(A.x)
>>> 1

发现类属性并没有被改变

查阅多方资料后,发现这种情况和实例的创建规则有关

class A:
    x=1

a=A()
print(id(a.x))
print(id(A.x))
A.x=2
print(id(a.x))
print(id(A.x))
a.x=4
print(id(a.x))
print(id(A.x))

>>>140722909176464         #显然开始实例属性会指向类属性,他们是同一个地址
>>>140722909176464

>>>140722909176496         #改变了类属性,实例属性会跟着转变指向新的地址
>>>140722909176496

>>>140722909176560         #但是改变了实例的属性,对象创建了自己的x,看到地址改变了
>>>140722909176496 #而类属性并不受影响

 

但是

def out():
print("我被创建了")

class A:
  x = 1
def __init__(self):
out()

class B:
t=A()
>>> “我被创建了”

#对象作为属性时,在定义时就被创建处一个A对象,后续不会再次创建
#这就是它与普通属性的本质区别了。
s1 = B()    
s1.t.x = 2          #改变了对象的属性,理应创建自己的t
print(id(B.t))
print(id(s1.t))
>>>1730846532384      #但是和上面的普通属性不同,这里s1没有创建一个新的A类实例,而是用了同一个对象t,所以后来再创建s2也是沿用t,自然看到x被改变了
>>>1730846532384      #打印出A类的x,发现并没有被改变,这也证明了它们并没有改变A的类属性。而是用的都是同一个A的实例t




 

以上是关于Python类的组合时产生的属性同步改变问题的主要内容,如果未能解决你的问题,请参考以下文章

组合继承

python3 类 组合

python之路--day21--组合与封装

类的组合与封装

python类的三大特征

Python之面向对象的组合多态菱形问题子类中重用父类的两种方式