如何将新实例初始化为已有实例?Python类初始化优化问询
解决Python中__init__里直接替换self实例的问题
嘿,这个问题我太懂了!在Python的__init__里直接给self赋值根本没用——因为self只是方法的局部参数,修改它不会改变已经创建好的实例引用。不过有两个靠谱的办法能实现你想要的效果,不用手动挨个复制属性:
方法1:用__new__直接返回目标实例(推荐)
__new__才是Python类中负责创建实例的方法,__init__只是用来初始化已经创建好的实例。所以如果你的场景是要返回一个已有的实例(比如Foo(Foo(x))),直接在__new__里返回目标实例是最干净的方案。
修改你的代码如下:
from variadic_foo_operations import foo_addition, foo_multiplication class Foo(object): def __new__(cls, arg=None, addends=None, factors=None): case_arg = arg is not None case_normal = case_arg and type(arg) == int case_trivial = case_arg and type(arg) == Foo case_add = addends is not None case_multiply = factors is not None case_variadic = case_add or case_multiply if case_trivial: # 直接返回传入的Foo实例,无需创建新对象 return arg elif case_variadic: operation = foo_addition if case_add else foo_multiplication operands = addends if case_add else factors current_foo = Foo(0) if case_add else Foo(1) # 取运算的中性元素 for operand_foo in operands: current_foo = operation(current_foo, operand_foo) # 返回计算好的目标实例 return current_foo elif case_normal: # 正常创建实例,交给__init__初始化 return super().__new__(cls) else: # 处理默认情况(arg=None) return super().__new__(cls) def __init__(self, arg=None, addends=None, factors=None): # 只有正常初始化的情况才执行赋值逻辑 case_arg = arg is not None case_normal = case_arg and type(arg) == int if case_normal: self.bar = arg self.double_bar = 2 * arg # trivial和variadic场景已经在__new__返回了实例,这里无需操作
这个方案的好处:
Foo(Foo(x))会直接返回原实例,不仅==成立,连is判断(身份相等)也成立,完全符合你的预期- variadic场景下直接返回计算好的实例,跳过了不必要的初始化步骤,效率更高
方法2:一行代码复制所有属性(适合不想改__new__的场景)
如果只是想在__init__里快速把目标实例的属性复制到当前self,可以用vars()方法操作实例的属性字典,一行代码搞定:
修改你__init__里的赋值部分:
if case_trivial or case_variadic: # 一行代码复制目标实例的所有属性到self vars(self).update(vars(the_foo_i_want))
解释:
vars(obj)会返回对象的__dict__属性(存储实例属性的字典)update()方法把目标实例的所有属性键值对复制到当前self的属性字典里,省去了手动逐个赋值的麻烦
⚠️ 注意:如果你的类定义了__slots__,这个方法会失效(因为有__slots__的实例没有__dict__),但你的示例代码里没有用到__slots__,所以完全适用。
内容的提问来源于stack exchange,提问作者Watchduck
相关产品推荐
相关产品推荐

