
简而言之,
__new__
__init__
在我看来,理解
__new__
__init__
__new__
__init__
当我们写
MyClass(arg1, arg2)
MyClass.__new__(MyClass, arg1, arg2)
@classmethod
cls
super().__new__(cls)
__new__
__new__
__init__
__new__
MyClass
self
MyClass.__init__(self, arg1, arg2)
__init__
None
我个人觉得,对于大多数日常编程任务,我们几乎只会和
__init__
__new__
class MyClass:
def __new__(cls, *args, **kwargs):
print(f"__new__ called for class {cls.__name__} with args: {args}, kwargs: {kwargs}")
# 实际创建实例,通常通过调用父类的__new__
instance = super().__new__(cls)
print(f"Instance created by __new__: {instance}")
return instance
def __init__(self, name, value):
print(f"__init__ called for instance {self} with name: {name}, value: {value}")
self.name = name
self.value = value
print(f"Instance initialized: {self.name}, {self.value}")
# 看看实际运行效果
print("--- Creating an instance ---")
obj = MyClass("TestObject", 123)
print(f"Final object: {obj.name}, {obj.value}")
print("\n--- What if __new__ returns something else? ---")
class AnotherClass:
def __new__(cls, *args, **kwargs):
print(f"AnotherClass.__new__ called, but returning a string.")
return "I am not an instance of AnotherClass!"
def __init__(self, *args, **kwargs):
print(f"AnotherClass.__init__ called. This should not happen if __new__ returns non-instance.")
self.data = "initialized data"
# 尝试创建AnotherClass的实例
not_an_instance = AnotherClass("hello")
print(f"Returned by constructor: {not_an_instance}")
# 你会发现__init__并没有被调用__new__
这是一个很好的问题,因为在日常开发中,我们很少会去动
__new__
实现单例模式 (Singleton Pattern): 当你希望一个类在整个应用程序生命周期中只创建一个实例时,
__new__
__new__
__init__
__init__
class Singleton:
_instance = None # 用于存储单例实例
def __new__(cls, *args, **kwargs):
if cls._instance is None:
print("Creating the one and only instance...")
cls._instance = super().__new__(cls)
else:
print("Returning existing instance...")
return cls._instance
def __init__(self, name):
# 注意:如果每次都创建新实例,__init__会被反复调用。
# 对于单例,如果想只初始化一次,需要在__init__中也做判断。
if not hasattr(self, '_initialized'): # 确保只初始化一次
print(f"Initializing instance with name: {name}")
self.name = name
self._initialized = True
else:
print(f"Instance already initialized. New name '{name}' ignored.")
s1 = Singleton("First Instance")
print(f"s1.name: {s1.name}")
s2 = Singleton("Second Instance") # 这里的"Second Instance"不会改变s1的name
print(f"s2.name: {s2.name}")
print(f"s1 is s2: {s1 is s2}") # True,证明是同一个实例你会看到,
__new__
__init__
创建不可变对象 (Immutable Objects): 如果你希望创建一个像
tuple
str
__new__
__init__
__new__
子类化不可变类型: 当你尝试子类化像
int
str
tuple
__new__
__init__
class MyString(str):
def __new__(cls, content):
# 必须调用str的__new__来创建str实例
instance = super().__new__(cls, content.upper())
print(f"MyString instance created with: {instance}")
return instance
def __init__(self, content):
# __init__在这里可以做一些额外的事情,但不能改变str的内部值
print(f"MyString __init__ called for {self}, original content was: {content}")
self.extra_data = "some_extra_info"
my_str = MyString("hello world")
print(f"Result: {my_str}, type: {type(my_str)}")
print(f"Extra data: {my_str.extra_data}")元类 (Metaclasses) 的实现: 虽然这有点超出了普通对象创建的范畴,但元类本身就是通过重写
type
__new__
__new__
__new__
__init__
这是一个非常关键的区别,也是初学者容易混淆的地方。我来详细拆解一下:
*`new(cls, args, kwargs)`
cls
__new__
__new__
*args
**kwargs
MyClass(arg1, arg2, key=value)
__new__
*`init(self, args, kwargs)`
self
__init__
__new__
__init__
self
和
__new__
__init__
我们可以用一个简单的流程图来想象这个参数传递:
MyClass(param1, param2)
MyClass.__new__(MyClass, param1, param2)
__new__
MyClass
obj
obj.__init__(param1, param2)
注意,
__new__
cls
__init__
self
cls
self
__new__
super().__new__(cls, ...)
cls
self
__new__
这是一个非常有意思的“分支点”,也是理解
__new__
__new__
cls
具体来说,会发生以下情况:
__init__
__init__
self
__new__
__init__
__new__
MyClass(...)
class MySpecialClass:
def __new__(cls, value):
print(f"MySpecialClass.__new__ called with value: {value}")
if value < 0:
print("Value is negative, returning a string instead of an instance.")
return "Error: Negative value not allowed!"
else:
print("Value is non-negative, proceeding with instance creation.")
return super().__new__(cls)
def __init__(self, value):
# 这个方法只有在__new__返回MySpecialClass的实例时才会被调用
print(f"MySpecialClass.__init__ called with value: {value}")
self.value = value
self.is_valid = True
obj1 = MySpecialClass(10)
print(f"obj1 type: {type(obj1)}, value: {obj1.value if hasattr(obj1, 'value') else 'N/A'}")
print("\n--- Testing with negative value ---")
obj2 = MySpecialClass(-5)
print(f"obj2 type: {type(obj2)}, value: {obj2}") # obj2现在是一个字符串!
# 尝试访问obj2.value会导致AttributeError
# print(obj2.value) # 这会报错你可以返回任意类型的对象。
__new__
str
int
list
潜在的混淆和调试难度。 虽然这种行为提供了极大的灵活性,但如果滥用,也可能导致代码难以理解和调试。当一个类的构造函数返回的不是该类的一个实例时,可能会让使用者感到困惑,因为这打破了常规的对象创建预期。因此,我个人建议,除非有非常明确和充分的理由(比如前面提到的单例模式或子类化不可变类型),否则最好让
__new__
cls
这个特性是 Python 允许我们深度定制对象创建过程的体现,它赋予了我们对对象生命周期更底层的控制能力。但就像所有强大的工具一样,使用时也需要谨慎和深思熟虑。
以上就是__new__和__init__方法有什么区别?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号