deepcopy 不保留类静态属性是设计行为,因其仅复制实例状态而非类定义;验证需用 hasattr(类, '属性名'),修复可用 type() 重建类或手动赋值。

类的静态属性在深拷贝过程中不会被保留,这不是 bug,而是 copy.deepcopy 的设计行为——它只复制“实例状态”,不复制类定义层面的结构。识别该现象的关键是:拷贝后访问类属性返回 AttributeError 或 False,而原类仍可正常访问。
如何快速识别静态属性丢失
执行深拷贝后立即验证类级别属性是否存在,而非实例属性:
- 用
hasattr(类对象, '静态属性名')检查,不是hasattr(实例, '静态属性名') - 对比
原类.__dict__和拷贝类.__dict__,会发现后者缺少类体中直接定义的键(如'foo') - 若拷贝后调用
拷贝类.foo报AttributeError,但原类.foo正常,即为典型丢失
为什么 deepcopy 不保留静态属性
copy.deepcopy 对类对象的处理逻辑是:将类视为一种“可调用对象”,仅复制其 __dict__ 中的运行时动态添加项(如通过 setattr(类, 'x', 1) 添加的),而忽略类定义时声明的静态属性(即写在 class body 里的赋值语句)。这些属性实际存储在类的 __dict__ 中,但 deepcopy 在重建类时未重建整个类结构,只做浅层字典复制。
手动补偿的两种可靠方案
不依赖 deepcopy 复制类本身,而是显式重建类并注入原始静态属性:
-
用 type() 重建类:
NewClass = type('NewClass', OriginalClass.__bases__, dict(OriginalClass.__dict__))。这完整复刻了类名、父类、全部类属性(含函数、描述符、静态变量) -
按需补全关键属性:若只需恢复特定静态字段,可直接赋值:
copied_class.foo = OriginalClass.foo;注意对不可变对象(如字符串、数字)安全,对可变对象(如列表、字典)需额外copy.deepcopy其值
避免踩坑的实践建议
静态属性本就不该依赖“拷贝”来传递——它属于类契约的一部分。更健壮的做法是:
- 把需跨类共享的状态改用模块级变量或配置对象管理
- 若必须生成新类,优先用
type()或types.new_class()显式构造,而非对原类调用deepcopy - 测试时增加断言:
assert hasattr(NewClass, 'expected_attr'),防止重构后遗漏

















