Python父类property与子类方法重写争议:我与作者谁正确?
Python中property继承的行为争议分析
在《Python技术手册》(Python in a Nutshell)中,作者指出以下代码存在“问题”——子类重写
f方法后,实例的g属性没有返回预期的42:class B: def f(self): return 23 g = property(f) class C(B): def f(self): return 42 c = C() print(c.g) # 输出: 23, 而非42作者给出的解决方案是在父类中增加一层间接调用,让
property的getter动态指向实例的f方法:class B: def f(self): return 23 def _f_getter(self): return self.f() g = property(_f_getter) class C(B): def f(self): return 42 c = C() print(c.g) # 输出: 42, 符合预期
争议核心:父类设计逻辑与语言默认行为的冲突
你的两个异议点完全站得住脚:
上游父类无需默认适配下游子类的扩展需求
父类作为通用逻辑的封装,设计时不该预设子类会重写某个方法,更没必要为了这种不确定的需求额外增加间接调用层。如果父类的g属性原本就绑定固定的B.f行为,强行加_f_getter反而违背了父类的设计初衷——只有当父类明确希望开放“通过重写f定制g”的扩展能力时,这种设计才合理,否则属于过度设计。子类未显式重写属性时,应严格继承父类行为
按照Python的继承机制,子类C没有重新定义g属性,就会完整继承父类B的g(即绑定了B.f的property对象)。类属性在定义阶段就完成了绑定,子类继承的是父类已经定义好的property,而非动态生成的新属性。所以c.g返回23是完全符合语言规则的,不能因为子类重写了f就默认改变g的行为——如果子类需要g响应f的重写,应该显式重写g属性,比如:
class C(B): def f(self): return 42 g = property(f)
结论:双方是基于不同设计目标的选择,无绝对对错
- 作者的方案是父类主动支持子类扩展的设计思路,适合父类希望开放定制能力的场景;
- 你的观点更贴合Python默认继承逻辑与模块化设计原则,上游父类保持自身逻辑独立性,子类需要修改行为时显式声明,避免隐式依赖带来的意外。
内容的提问来源于stack exchange,提问作者Jim
相关产品推荐
相关产品推荐

