
在python中,对象的生命周期通常涉及两个特殊方法:
*`new(cls, args, kwargs)`:
*`init(self, args, kwargs)`:
调用顺序总结: 当你创建一个类的实例时(例如obj = MyClass()),Python解释器会首先调用MyClass.__new__()来创建实例。如果__new__成功创建并返回了一个MyClass的实例,那么解释器会接着调用该实例的MyClass.__init__()方法来对其进行初始化。
__new__通常只在需要控制实例创建过程的特殊场景下重写,例如:
在重写__new__时,务必遵循以下原则:
立即学习“Python免费学习笔记(深入)”;
当存在继承关系时,__new__和__init__的调用行为会更加复杂:
我们通过一个示例来深入理解__new__和__init__的复杂交互,特别是当__new__被错误实现时。
考虑以下有问题的代码:
class Demo:
def __new__(self): # 错误:__new__应接收cls作为第一个参数
self.__init__(self) # 陷阱:在__new__中手动调用__init__
print("Demo's __new__() invoked")
# 隐式返回None,因为没有显式return
def __init__(self):
print("Demo's __init__() invoked")
class Derived_Demo(Demo):
def __new__(self): # 错误:__new__应接收cls作为第一个参数
print("Derived_Demo's __new__() invoked")
# 隐式返回None,因为没有显式return
def __init__(self):
print("Derived_Demo's __init__() invoked")
def main():
obj1 = Derived_Demo()
print(f"obj1 is: {obj1}") # 观察obj1的值
obj2 = Demo()
print(f"obj2 is: {obj2}") # 观察obj2的值
main()运行上述代码的输出:
Derived_Demo's __new__() invoked Demo's __init__() invoked Demo's __new__() invoked obj1 is: None obj2 is: None
输出分析:
obj1 = Derived_Demo() 调用 Derived_Demo.__new__():
obj2 = Demo() 调用 Demo.__new__():
为了避免上述问题,并确保__new__和__init__按预期工作,我们应该这样实现它们:
class Demo:
def __new__(cls, *args, **kwargs): # 正确:第一个参数是cls
print("Demo's __new__() invoked")
# 正确:通过super()调用父类(object)的__new__来创建实例
instance = super().__new__(cls)
return instance # 正确:返回创建的实例
def __init__(self, value=None): # 可以有参数,用于初始化实例
print(f"Demo's __init__() invoked with value: {value}")
self.value = value
class Derived_Demo(Demo):
def __new__(cls, *args, **kwargs): # 正确:第一个参数是cls
print("Derived_Demo's __new__() invoked")
# 正确:通过super()调用父类(Demo)的__new__来创建实例
instance = super().__new__(cls)
return instance # 正确:返回创建的实例
def __init__(self, name=None): # 可以有参数,用于初始化实例
super().__init__(name) # 调用父类的__init__
print(f"Derived_Demo's __init__() invoked with name: {name}")
self.name = name
def main():
print("--- Creating obj1 ---")
obj1 = Derived_Demo(name="Alice")
print(f"obj1 is: {obj1}")
print(f"obj1.name: {obj1.name}")
print(f"obj1.value: {obj1.value}") # 继承自Demo的属性
print("\n--- Creating obj2 ---")
obj2 = Demo(value=123)
print(f"obj2 is: {obj2}")
print(f"obj2.value: {obj2.value}")
main()运行正确代码的输出:
--- Creating obj1 --- Derived_Demo's __new__() invoked Demo's __new__() invoked Demo's __init__() invoked with value: Alice Derived_Demo's __init__() invoked with name: Alice obj1 is: <__main__.Derived_Demo object at 0x...> obj1.name: Alice obj1.value: Alice --- Creating obj2 --- Demo's __new__() invoked Demo's __init__() invoked with value: 123 obj2 is: <__main__.Demo object at 0x...> obj2.value: 123
正确代码分析:
obj1 = Derived_Demo(name="Alice"):
obj2 = Demo(value=123):
理解__new__和__init__的正确用法对于编写健壮和高效的Python代码至关重要,尤其是在处理复杂的类结构和对象创建逻辑时。
以上就是深入理解Python中__new__与__init__的执行机制及常见陷阱的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号