Python __new__ 方法
最后修改于 2025 年 4 月 8 日
本综合指南探讨了 Python 的 __new__ 方法,这是负责对象创建的特殊方法。我们将涵盖基本用法、不可变对象、单例模式、元类以及实际示例。
基本定义
__new__ 方法是一个静态方法,用于创建并返回类的新实例。它在 __init__ 之前被调用,并负责对象分配。
关键特征:它必须接受类作为第一个参数(通常命名为 cls),返回新实例,并且可以被重写以自定义对象创建。与 __init__ 不同,它控制创建过程。
基本 __new__ 实现
这是展示 __new__ 在对象创建生命周期中作用的最简单实现。它演示了它如何与 __init__ 一起工作。
class Example:
def __new__(cls, *args, **kwargs):
print("__new__ called")
instance = super().__new__(cls)
return instance
def __init__(self, value):
print("__init__ called")
self.value = value
obj = Example(42)
print(obj.value)
此示例展示了对象创建的顺序。__new__ 创建实例,然后 __init__ 初始化它。输出将在“__init__ called”之前显示“__new__ called”。
super().__new__(cls) 调用至关重要——它使用父类的 __new__ 方法(通常是 object.__new__)来创建实际的实例。
创建不可变对象
在创建元组或自定义不可变类等不可变类型时,__new__ 是必不可少的,因为它可以防止创建后进行修改。
class ImmutablePoint:
def __new__(cls, x, y):
instance = super().__new__(cls)
instance._x = x
instance._y = y
return instance
@property
def x(self):
return self._x
@property
def y(self):
return self._y
def __repr__(self):
return f"Point({self.x}, {self.y})"
point = ImmutablePoint(3, 4)
print(point)
# point.x = 5 # Would raise AttributeError
这个不可变点类通过 __new__ 在创建时设置坐标,并通过只读属性暴露它们。尝试修改它们将引发 AttributeError。
实例变量在返回实例之前在 __new__ 中设置,使其成为初始对象状态的一部分。这种模式对于不可变对象很常见。
实现单例模式
单例模式确保一个类只有一个实例。__new__ 可以通过控制实例创建来强制执行此操作。
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
print("Creating new instance")
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
print("Initializing Singleton")
s1 = Singleton()
s2 = Singleton()
print(s1 is s2) # True
此单例实现将单个实例存储在类变量中。__new__ 在创建新实例之前检查它是否存在。所有构造函数调用都返回相同的实例。
请注意,__init__ 每次都会被调用,这可能会重新初始化实例。为防止这种情况,您可以添加另一个标志或重构代码。
使用参数自定义对象创建
__new__ 可以检查参数并决定是否/如何创建实例,从而实现高级创建模式。
class LimitedInstances:
_count = 0
MAX_INSTANCES = 3
def __new__(cls, *args, **kwargs):
if cls._count >= cls.MAX_INSTANCES:
raise RuntimeError(f"Cannot create more than {cls.MAX_INSTANCES} instances")
cls._count += 1
return super().__new__(cls)
def __del__(self):
type(self)._count -= 1
objs = [LimitedInstances() for _ in range(3)] # Works
# LimitedInstances() # Raises RuntimeError
此类将活动实例的数量限制为 3。__new__ 在允许创建之前检查计数。当实例被垃圾回收时,__del__ 方法会减少计数。
这种模式对于资源受限的场景很有用,例如数据库连接或线程池,您希望强制执行实例限制。
元类 __new__ 方法
在元类中,__new__ 控制类创建(而不是实例创建),允许动态修改类。
class Meta(type):
def __new__(mcls, name, bases, namespace):
print(f"Creating class {name}")
namespace['version'] = 1.0
return super().__new__(mcls, name, bases, namespace)
class MyClass(metaclass=Meta):
pass
print(MyClass.version) # 1.0
这个元类为它创建的每个类添加一个 version 属性。元类的 __new__ 在类被构造之前修改类命名空间。
元类 __new__ 接收不同的参数:元类本身、类名、基类以及包含类属性的命名空间字典。
最佳实践
- 始终调用 super().__new__: 除非有意阻止创建
- 返回正确类型: 确保返回的对象是 cls 的实例
- 考虑 __init__: __new__ 中的更改可能会影响初始化
- 记录行为: 清楚地记录任何特殊的创建逻辑
- 尽可能优先使用 __init__: 仅在必要时使用 __new__
资料来源
作者
列出所有 Python 教程。