Python中不使用继承复制类/实例属性的最优实现方案
Python中不使用继承复制类/实例属性的最优实现方案
老哥,完全懂你的处境——继承只是偶尔才用的例外情况,绝大多数时候不需要,现在你需要的是把一个实例的属性复制给另一个,不想走继承的路子,你的现有方法能跑,但确实有更简洁高效的实现方式,咱来唠唠:
首先先看看你当前的代码思路:遍历父实例的__dict__拿到属性名,过滤掉双下划线开头的特殊属性,再逐个把值赋给子实例。这个逻辑没问题,但可以简化得更优雅。
优化方案1:直接遍历键值对,减少一次属性查找
你原来先拿属性名再用getattr取值,其实可以直接遍历__dict__.items()拿到键值对,一步到位:
def copy_class(child, parent): for attr, value in parent.__dict__.items(): if not attr.startswith("__"): setattr(child, attr, value)
这样少了一次getattr的调用,代码更紧凑,效率也稍高一点。
优化方案2:用__dict__.update批量赋值,更简洁
如果想更省事,直接用实例的__dict__的update方法批量更新,这是Python里字典操作的原生高效方法:
def copy_class(child, parent): # 直接复制所有非特殊属性到子实例的__dict__ child.__dict__.update({ attr: value for attr, value in parent.__dict__.items() if not attr.startswith("__") })
如果不需要过滤特殊属性(比如你能确定父实例的__dict__里没有需要排除的特殊属性),甚至可以直接写:
def copy_class(child, parent): child.__dict__.update(parent.__dict__)
这一行就搞定了,超级简洁!
注意:可变对象的深拷贝问题
上面的方法都是浅拷贝——如果属性是列表、字典这类可变对象,子实例会和父实例共享同一个对象引用,修改其中一个的属性值会影响另一个。要是需要完全独立的拷贝,就得用上copy模块的deepcopy:
import copy def copy_class(child, parent): child.__dict__.update({ attr: copy.deepcopy(value) for attr, value in parent.__dict__.items() if not attr.startswith("__") })
这样不管属性是可变还是不可变,子实例都会拿到完全独立的副本,不会和父实例互相影响。
用你的例子测试优化后的代码
咱把优化后的代码代入你的例子试试,完全能正常工作:
class cool_class(): def __init__(self): self.hey_you = 1 import copy def copy_class(child, parent): child.__dict__.update({ attr: copy.deepcopy(value) for attr, value in parent.__dict__.items() if not attr.startswith("__") }) ins = cool_class() ins.get_off_my_cloud = 1 # 加个可变属性测试深拷贝 ins.my_list = [1, 2, 3] ins2 = cool_class() copy_class(ins2, ins) assert ins2.get_off_my_cloud == 1 assert ins2.hey_you == 1 # 修改子实例的可变属性,父实例不受影响 ins2.my_list.append(4) assert ins.my_list == [1, 2, 3] assert ins2.my_list == [1, 2, 3, 4]
完美通过测试,还解决了可变对象的引用问题~
备注:内容来源于stack exchange,提问作者bobsmith76
相关产品推荐
相关产品推荐

