ZetCode

Python __new__ 方法

最后修改于 2025 年 4 月 8 日

本综合指南探讨了 Python 的 __new__ 方法,这是负责对象创建的特殊方法。我们将涵盖基本用法、不可变对象、单例模式、元类以及实际示例。

基本定义

__new__ 方法是一个静态方法,用于创建并返回类的新实例。它在 __init__ 之前被调用,并负责对象分配。

关键特征:它必须接受类作为第一个参数(通常命名为 cls),返回新实例,并且可以被重写以自定义对象创建。与 __init__ 不同,它控制创建过程。

基本 __new__ 实现

这是展示 __new__ 在对象创建生命周期中作用的最简单实现。它演示了它如何与 __init__ 一起工作。

basic_new.py
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__ 是必不可少的,因为它可以防止创建后进行修改。

immutable.py
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__ 可以通过控制实例创建来强制执行此操作。

singleton.py
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__ 可以检查参数并决定是否/如何创建实例,从而实现高级创建模式。

conditional_creation.py
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__ 控制类创建(而不是实例创建),允许动态修改类。

metaclass.py
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__ 接收不同的参数:元类本身、类名、基类以及包含类属性的命名空间字典。

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。

列出所有 Python 教程