父类实例变量被子类覆盖:如何让父类方法输出原变量值?
class Foo: def __init__(self): self.model = "A" def create(self): print(f"Model in class {self.model}") class Bar(Foo): def __init__(self): super().__init__() self.model = "B" def save(self): super().create() print(f"Model in class Bar {self.model}") bar = Bar() bar.save()
输出:
Model in class Foo B
Model in class Bar B
问题
为何父类Foo中的实例变量model会被子类覆盖?这是正常预期行为吗?我希望父类方法执行时输出“A”,当前代码存在什么问题?
解答
父类实例变量被覆盖的原因
Python中子类实例和父类方法共享同一个实例属性空间。你的Bar类__init__方法先调用super().__init__(),给实例的model赋值为"A",紧接着又将self.model改为"B"——这直接修改了同一个实例的属性值。当父类create方法执行时,它访问的是当前Bar实例的model属性,自然就是已经被修改后的"B"。是否属于正常预期行为
是的,这完全符合Python的属性查找规则。实例属性是全局绑定在实例上的,父类方法访问的也是当前实例的属性,所以子类对实例属性的修改会被父类方法感知到。当前代码的问题与解决思路
当前代码的核心矛盾是:你在子类初始化时覆盖了父类设置的实例属性,却期望父类方法访问未修改前的值。要实现父类方法输出"A",可以参考以下几种方案:
- 调整赋值顺序:把
self.model = "B"移到调用父类方法之后。比如在Bar的save方法里,先执行super().create(),再给self.model赋值,这样父类方法执行时用的还是初始的"A"。 - 改用类属性:如果父类的
model不需要每个实例单独定制,可以将其设为类属性,让父类方法直接访问类本身的属性,不受子类实例属性影响:class Foo: model = "A" def create(self): print(f"Model in class {Foo.model}") - 子类使用独立属性名:子类避免使用
model作为属性名,改用bar_model这类专属名称,从根源上避免属性冲突。 - 父类保留初始属性:在父类
__init__中把初始值存入独立属性(比如self._base_model = "A"),然后create方法输出这个属性,子类修改model就不会影响父类方法的输出。
内容的提问来源于stack exchange,提问作者ABHIJITH EA
相关产品推荐
相关产品推荐

