python中__new__函数的具体使用
作者:Lumiron
new是object基类提供的内置静态方法,本文主要介绍了python中__new__函数的具体使用,具有一定的参考价值,感兴趣的可以了解一下
__new__函数的介绍
new 是object基类提供的内置静态方法(虽然通常不需要显式地使用 @staticmethod 装饰器)。
__new__函数的作用
总结:它的作用是为一个类创建并返回一个新的实例。
1、在内存中分配对象的空间。
2、返回对象的引用。
__new__函数的重写
如果因为__new__函数重写导致没有正确的返回实例化对象的引用,__init__函数将不被调用。
1、重写代码示例:
注意点:
1、重写时需要调用super,对父类做扩展。
2、需要返回super的返回值,即实例的引用。(博主在这里认为如果不返回实例的引用,会有内存泄漏)
class MyClass: def __new__(cls, *args, **kwargs): print("__new__ is called. Creating instance.") # 最关键的一步:调用父类的 __new__ 来创建实例 instance = super().__new__(cls) # 这里可以对 instance 做一些非常早期的操作 return instance # 必须返回实例! def __init__(self, value): print("__init__ is called. Initializing instance.") self.value = value # 测试 obj = MyClass(42) print(obj.value)
输出:
__new__ is called. Creating instance.
__init__ is called. Initializing instance.
42
2、错误重写方法1:
重写__new__方法,直接覆盖。无法成功的实例化对象。
class MyClass: def __new__(cls, *args, **kwargs): print("__new__ is called. Creating instance.") def __init__(self, value): print("__init__ is called. Initializing instance.") self.value = value # 测试 obj = MyClass(42) print(obj)
输出
__new__ is called. Creating instance.
None
3、错误重写方法2:
调用了父类的__new__创建实例,但是未返回实例的引用。
class MyClass: def __new__(cls, *args, **kwargs): print("__new__ is called. Creating instance.") # 最关键的一步:调用父类的 __new__ 来创建实例 super().__new__(cls) def __init__(self, value): print("__init__ is called. Initializing instance.") self.value = value # 测试 obj = MyClass(42) print(obj)
输出
__new__ is called. Creating instance.
None
4. __new__函数 的常见用途
用途 1:实现单例模式 (Singleton)
单例模式确保一个类只有一个实例。
class Singleton: _instance = None # 类变量,用于保存唯一的实例 def __new__(cls, *args, **kwargs): # 如果实例还不存在,就创建一个 if not cls._instance: cls._instance = super().__new__(cls) # 如果已经存在,直接返回已有的实例 # 注意:每次调用 Singleton(),__init__ 仍然会被重新执行 return cls._instance def __init__(self, name): self.name = name # 测试 s1 = Singleton("First") s2 = Singleton("Second") print(s1 is s2) # 输出: True,它们是同一个对象 print(s1.name) # 输出: "Second" (注意!因为 __init__ 被第二次调用覆盖了)
注意:上面的例子有一个“陷阱”,第二次创建实例时,init 依然会执行并修改了唯一实例的属性。要避免这个问题,需要更复杂的控制。
用途 2:继承不可变类型 (如 int, str, tuple)
不可变类型在 init 里无法被修改,因为对象在 init 被调用前就已经创建好了。所以必须在 new 阶段就修改它们。
class PositiveInteger(int): def __new__(cls, value): # 在创建对象之前,先对值进行加工 return super().__new__(cls, abs(value)) # 测试 num = PositiveInteger(-5) print(num) # 输出: 5 (是一个真正的 int 类型) print(type(num)) # 输出: <class '__main__.PositiveInteger'>
用途 3:返回其他类的实例(工厂模式)
new 可以决定返回什么对象,不一定是当前类的实例。
class ClassA: pass class ClassB: pass class MyFactory: def __new__(cls, obj_type): if obj_type == 'A': return ClassA() elif obj_type == 'B': return ClassB() else: return None # 测试 obj1 = MyFactory('A') obj2 = MyFactory('B') print(type(obj1)) # 输出: <class '__main__.ClassA'> print(type(obj2)) # 输出: <class '__main__.ClassB'>
new与init的区别
特性 | new | init |
---|---|---|
作用 | 创建对象,并返回这个新对象 | 初始化已被创建的对象 |
调用顺序 | 先调用 | 后调用 |
参数 | 第一个参数是 cls (类本身) | 第一个参数是 self (实例本身) |
返回值 | 必须返回创建的对象实例(通常是 cls 的实例) | 不应该返回任何值(返回 None) |
本质 | 它是一个静态方法 | 它是一个实例方法 |
到此这篇关于python实现__new__函数的文章就介绍到这了,更多相关python __new__函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!