
本文介绍一种 Pythonic 的方式,通过延迟求值默认参数来实现在类实例化前动态修改类变量(如 bar),从而让子类 B 的 __new__ 方法始终使用最新值调用父类 A,无需侵入第三方类或逐层修改继承链。
本文介绍一种 pythonic 的方式,通过延迟求值默认参数来实现在类实例化前动态修改类变量(如 `bar`),从而让子类 `b` 的 `__new__` 方法始终使用最新值调用父类 `a`,无需侵入第三方类或逐层修改继承链。
在 Python 中,函数/方法的默认参数值仅在定义时求值一次(而非每次调用时),这是导致原始代码中 foo=bar 无法响应后续 B.bar = 'bar2' 修改的根本原因。因此,直接将类变量作为默认参数是无效的。
正确的做法是:将默认参数设为一个占位符(如 None 或自定义哨兵对象),并在 __new__ 方法体内按需读取当前类变量值。这样就能确保每次实例化时都获取最新的 cls.bar 值。
以下是推荐的实现方案:
class A(object):
def __new__(cls, foo):
print('foo seen by A:', foo)
return super().__new__(cls)
class B(A):
bar = "bar1"
def __new__(cls, foo=None):
if foo is None:
foo = cls.bar
return super().__new__(cls, foo=foo)
✅ 使用示例:
if __name__ == '__main__':
b1 = B() # 输出: foo seen by A: bar1
B.bar = 'bar2'
b2 = B() # 输出: foo seen by A: bar2
print(b2.bar) # 输出: bar2
⚠️ 注意事项:
避免使用可变对象(如
[]或{})作为默认参数——这虽能“绕过”问题,但属于反模式,易引发意外共享状态。若
None在业务逻辑中有实际含义(例如表示“无输入”),请改用私有哨兵对象(如object()),确保语义清晰且绝对唯一:_NO_FOO = object() class B(A): bar = "bar1" def __new__(cls, foo=_NO_FOO): if foo is _NO_FOO: foo = cls.bar return super().__new__(cls, foo=foo)
该方案完全符合 Python 惯例,简洁、安全、可维护,并天然兼容任意深度的继承链(所有子类均自动继承此行为,无需额外适配)。用户只需修改 B.bar 即可全局生效,真正实现“配置即代码”的轻量定制目标。










