Python类变量本质是共享引用,赋值操作会切断继承链上的共享;可变类变量未屏蔽时子类间意外共享,正确做法是显式为子类定义或用@classmethod封装。

Python 没有真正的“静态变量”概念,所谓“类变量”在继承中表现异常,根本原因在于类对象的属性查找机制和赋值行为不一致——读取时走 MRO,写入时却直接绑定到当前类。
类变量赋值会屏蔽父类同名属性
当你对子类做 Child.attr = value,Python 不会修改父类的 attr,而是直接在 Child.__dict__ 中新建一个同名条目。后续通过 Child.attr 读取时,MRO 查找停在子类;但通过 Parent.attr 或未被覆盖的实例仍读父类原始值。
- 父类定义
Base.count = 0,子类执行Child.count = 1→Child获得独立副本 -
Base.count仍是0,不受影响 - 若子类未赋值,
Child.count会沿 MRO 找到Base.count,返回0
可变类变量在子类间意外共享
如果父类定义了可变类变量(如 list、dict),而子类未重新赋值,所有子类(及父类)实例操作的都是同一个对象。
-
class Base: items = []→Base.items是唯一列表 -
class A(Base): pass和class B(Base): pass都共享Base.items -
A.items.append(1)后,B.items也会看到[1] - 这不是“继承诡异”,而是所有类都引用同一对象 —— 和默认参数陷阱本质相同
子类初始化时误改父类类变量
常见错误是在子类 __init__ 中直接修改类变量,以为只影响本类,实则影响整个继承链上未屏蔽该变量的所有类。
立即学习“Python免费学习笔记(深入)”;
-
def __init__(self): Base.items.append(self.name)→ 所有继承自Base的类都会往同一个items里塞数据 - 正确做法:显式使用
self.__class__.items(仅当子类已屏蔽)或为每个子类单独定义类变量 - 更安全的方式:用
@classmethod封装修改逻辑,并在子类中重载
真正容易被忽略的是:类变量不是“静态副本”,而是一个被多个类名共享的引用;是否隔离,完全取决于你有没有在子类中执行过赋值操作 —— 这个动作本身就会切断共享,但多数人意识不到它发生了。


















