Python类继承并没有为我提供单独的列表实例

Python类继承并没有为我提供单独的列表实例,python,subclass,Python,Subclass,我不明白这里发生了什么。我有一个C类,它是B的一个子类。B有一个属性B,它是a类的一个实例。a有一个属性,一个叫做a的列表。当我初始化两个不同的C实例时,它们具有相同的A实例,因此当我附加到A.A时,它会导致两个C实例都具有附加属性b.A class A: a = list() class B: b = A() class C(B): pass one = C() two = C() one.b.a.append('one') one.b.a.append('two

我不明白这里发生了什么。我有一个C类,它是B的一个子类。B有一个属性B,它是a类的一个实例。a有一个属性,一个叫做a的列表。当我初始化两个不同的C实例时,它们具有相同的A实例,因此当我附加到A.A时,它会导致两个C实例都具有附加属性b.A

class A:
    a = list()

class B:
    b = A()

class C(B):
    pass

one = C()
two = C()
one.b.a.append('one')
one.b.a.append('two')
two.b.a.append('three')

print(one.b.a)
print(two.b.a)
运行此代码将打印出:

['one', 'two', 'three']
['one', 'two', 'three']

显然,一个.b.a和两个.b.a指向同一个对象,而我本来希望每次调用C时都会初始化一个新的a实例。为什么会发生这种情况以及如何解决它?

这是因为您将a和b声明为类属性而不是实例变量。可以将类属性视为该类的全局变量。对于所有对象,类属性只能有一个值

另一方面,实例变量对于类的每个实例都是唯一的。有关更深入的解释,请参阅

总结如下:

class A:
    a = 'A'
    
    def __init__(self):
        self.b = 'B'

foo = A()
bar = A()

foo.a
>>> A

bar.a
>>> A

foo.b
>>> B

bar.b
>>> B

A.a = 'C'
foo.a
>>> C
bar.a
>>> C

foo.b = 'D'
bar.b
>>> B

这是因为您将a和b声明为类属性,而不是实例变量。可以将类属性视为该类的全局变量。对于所有对象,类属性只能有一个值

另一方面,实例变量对于类的每个实例都是唯一的。有关更深入的解释,请参阅

总结如下:

class A:
    a = 'A'
    
    def __init__(self):
        self.b = 'B'

foo = A()
bar = A()

foo.a
>>> A

bar.a
>>> A

foo.b
>>> B

bar.b
>>> B

A.a = 'C'
foo.a
>>> C
bar.a
>>> C

foo.b = 'D'
bar.b
>>> B

A.A是一个列表。不是每个实例一个列表,而是整个类的一个列表。B.B也是整个B类的A的一个实例。类变量不同于实例变量,这在引用列表等可变对象时很重要。B有一个名为B的类属性。对于B.A.A的每个实例,您没有单独的列表。A.A是一个列表。不是每个实例一个列表,而是整个类的一个列表。B.B也是整个B类的A的一个实例。类变量不同于实例变量,这在引用列表等可变对象时很重要。B有一个名为B的类属性。对于B的每个实例,您没有单独的列表。此代码有一点不正确。设置foo.a='C'将创建一个实例变量foo.a。它不会改变bar.a的值。如果要从实例获取类变量,则需要调用foo.\uuuu class\uuuu.a。如上所述,设置foo.a只会创建一个实例变量,而不会影响bar。@khelwood woops,看起来你是对的,在添加my+1时做了一个编辑,因为我不知道类属性和实例属性之间的区别,这让我很生气!!这段代码有一点不正确。设置foo.a='C'将创建一个实例变量foo.a。它不会改变bar.a的值。如果要从实例获取类变量,则需要调用foo.\uuuu class\uuuu.a。如上所述,设置foo.a只会创建一个实例变量,而不会影响bar。@khelwood woops,看起来你是对的,在添加my+1时做了一个编辑,因为我不知道类属性和实例属性之间的区别,这让我很生气!!