Python中派生类实例共享父类letters属性的原因及两种实现方式的差异
为什么派生类A和B的实例会共享父类Parent的
letters属性? 这是个非常典型的Python类属性与实例属性混淆的问题,我来给你拆解清楚:
代码示例1的问题根源:类属性的共享特性
在第一个代码里,Parent类中的letters = list()是类属性——它属于Parent这个类本身,而不是某个具体的实例。
当你创建A或B的实例a和b时,这两个实例本身并没有自己的letters属性。当调用self.add()里的self.letters.append()时,Python会先在实例自身找letters,找不到就会向上追溯到父类Parent的类属性,所以a和b实际上操作的是同一个列表对象。
这就导致:
a.add_a()往共享列表里添加了'a'b.add_b()又往同一个共享列表里添加了'b'
最终两个实例的letters都会显示['a', 'b'],出现你说的“意外共享”情况。
代码示例2的解决方案:实例属性的独立性
而第二个代码把letters的定义放到了__init__方法里:self.letters = list(),这就把它变成了实例属性。
__init__是Python的实例初始化方法,每创建一个新实例时都会执行一次。也就是说,当你创建a = A()和b = B()时,a会生成一个属于自己的空列表,b也会生成另一个完全独立的空列表。
此时调用a.add_a()只会修改a自己的letters,b.add_b()只会修改b自己的letters,两者之间完全不会互相影响,这就是你预期的结果。
两种实现的核心差异
- 类属性:定义在类的顶层(不在任何方法内部),属于类本身,所有该类(包括子类)的实例都会共享这个属性的值。如果属性是可变对象(比如列表、字典),修改它会影响所有实例。
- 实例属性:通过
self.xxx在实例方法(通常是__init__)中定义,属于每个单独的实例,每个实例的属性都是独立的,修改不会波及其他实例。
内容的提问来源于stack exchange,提问作者vindarmagnus
相关产品推荐
相关产品推荐

