如何创建可通过自身实例初始化的Python类
实现支持自身实例初始化的类
要实现既能用原始数据初始化,又能用自身实例初始化的类,核心是在实例创建/初始化阶段判断输入参数类型,针对性处理。下面分两种场景给出实现方案:
方案1:返回原实例(满足instance2 is instance1)
如果需要直接复用传入的实例(新创建对象与传入实例为同一个引用),需重写类的__new__方法——它负责创建实例对象:
from typing import Mapping, Union class NewClass: """支持用映射类型或自身实例初始化的类""" def __new__(cls, obj: Union[Mapping, 'NewClass']): # 若传入自身实例,直接返回该实例 if isinstance(obj, cls): return obj # 否则创建新实例 return super().__new__(cls) def __init__(self, data: Union[Mapping, 'NewClass']): # 仅当输入不是自身实例时,执行初始化逻辑 if not isinstance(data, type(self)): self.data = data def cool_method(self): assert isinstance(self.data, Mapping) # 示例业务逻辑:返回data的键列表 return list(self.data.keys())
验证最简示例
arg = {"name": "test", "value": 123} instance1 = NewClass(arg) instance2 = NewClass(instance1) assert instance2 is instance1 # 断言成立,返回同一实例 assert instance2.data == instance1.data # 数据完全一致
适配复杂示例中的AnotherClass
class AnotherClass: """接受映射类型或NewClass实例,内部使用NewClass""" def __init__(self, obj: Union[Mapping, NewClass]): # 传入NewClass实例时,直接复用原实例,避免重复初始化 self.cool = NewClass(obj).cool_method()
方案2:创建新实例但属性一致(满足instance2 == instance1)
若不需要复用同一实例,仅要求新实例属性与传入实例一致,可仅在__init__中处理:
from typing import Mapping, Union class NewClass: def __init__(self, data: Union[Mapping, 'NewClass']): if isinstance(data, type(self)): # 复制传入实例的属性(用copy避免原数据被意外修改) self.data = data.data.copy() else: self.data = data def __eq__(self, other): # 定义相等判断逻辑,满足instance2 == instance1 if isinstance(other, type(self)): return self.data == other.data return False def cool_method(self): assert isinstance(self.data, Mapping) return list(self.data.keys())
验证示例
arg = {"name": "test", "value": 123} instance1 = NewClass(arg) instance2 = NewClass(instance1) assert instance2 == instance1 # 断言成立 assert instance2 is not instance1 # 为不同实例
关键要点
- 类型标注:用
Union[Mapping, 'NewClass']支持两种输入类型,'NewClass'是字符串形式的前向引用,避免类未定义时的报错。 - 实例判断:通过
isinstance(obj, cls)或isinstance(data, type(self))识别自身实例。 - 复用实例场景:必须重写
__new__,因为__init__无法返回新实例,只能初始化已创建的实例。
内容的提问来源于stack exchange,提问作者Nikolay Prokopyev
相关产品推荐
相关产品推荐

