Python 中 __new__的实现示例

 更新时间:2026年05月15日 09:02:25   作者:无风听海  
__new__是Python中负责分配并返回对象实例的方法,比__init__更早被调用,其主要区别在于调用时机、参数、返回值和职责,本文主要介绍了Python 中 __new__的实现示例,感兴趣的可以了解一下

__new__ 是 Python 中最底层的对象创建机制,它比 __init__ 更早被调用,真正负责分配并返回对象实例。理解它是掌握元类、单例、不可变类型定制等高级特性的基础。

一、__new__vs__init__的本质区别

class Foo:
    def __new__(cls, *args, **kwargs):
        print(f"[__new__] 分配内存,cls={cls}")
        instance = super().__new__(cls)  # 创建实例
        return instance                  # 必须 return!

    def __init__(self, value):
        print(f"[__init__] 初始化,self={self}")
        self.value = value

obj = Foo(42)
# [__new__] 分配内存,cls=<class 'Foo'>
# [__init__] 初始化,self=<__main__.Foo object>

关键区别:

__new____init__
调用时机实例创建之前实例创建之后
第一个参数cls(类本身)self(已有实例)
返回值必须返回实例必须返回 None
职责分配空间,构造对象初始化属性

__init__ 只有在 __new__ 返回了 cls 的实例时才会被调用。若返回其他类型,__init__ 会被跳过。

二、__new__的签名与调用链

object.__new__(cls[, *args, **kwargs])

Python 内部执行 Foo(42) 的等价逻辑是:

# type.__call__ 的内部行为(伪代码)
def __call__(cls, *args, **kwargs):
    obj = cls.__new__(cls, *args, **kwargs)
    if isinstance(obj, cls):        # 只有返回 cls 的实例才调 __init__
        obj.__init__(*args, **kwargs)
    return obj

下面是完整的对象创建生命周期:—

三、最重要的使用场景

1. 单例模式(Singleton)

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance  # 始终返回同一个实例

a = Singleton()
b = Singleton()
print(a is b)  # True

2. 定制不可变类型

strinttuple 等不可变类型必须在 __new__ 中完成初始化,因为一旦创建就无法修改:

class UpperStr(str):
    def __new__(cls, value):
        return super().__new__(cls, value.upper())
        # ⚠️ 不能在 __init__ 里改,str 是不可变的

s = UpperStr("hello")
print(s)        # HELLO
print(type(s))  # <class '__main__.UpperStr'>

3. 工厂模式 —— 根据参数返回不同类型

class Shape:
    def __new__(cls, kind, *args):
        subclasses = {"circle": Circle, "rect": Rect}
        target_cls = subclasses.get(kind, cls)
        return super().__new__(target_cls)

class Circle(Shape): pass
class Rect(Shape):   pass

s = Shape("circle")
print(type(s))  # <class '__main__.Circle'>

4. 元类(Metaclass)中的__new__

元类的 __new__ 控制类本身的创建(不是实例的创建):

class Meta(type):
    def __new__(mcs, name, bases, namespace):
        # 在类定义时,自动把所有方法名转大写
        new_ns = {k.upper() if not k.startswith('_') else k: v
                  for k, v in namespace.items()}
        return super().__new__(mcs, name, bases, new_ns)

class Foo(metaclass=Meta):
    def hello(self): return "hi"

Foo().HELLO()  # "hi"  — 方法被重命名了

四、常见陷阱

陷阱1:忘记 return

class Bad:
    def __new__(cls):
        super().__new__(cls)  # 没有 return!→ 返回 None
                              # __init__ 不会被调用,obj 是 None

陷阱2:__init__ 的参数必须与 __new__ 一致

# Python 会同时把参数传给 __new__ 和 __init__
# 若签名不匹配会报 TypeError

class Ok:
    def __new__(cls, x, y):      # 接受 x, y
        return super().__new__(cls)
    def __init__(self, x, y):    # 同样接受 x, y ✓
        self.x, self.y = x, y

陷阱3:super().__new__ 的参数

  • Python 3.3+ 后,object.__new__object.__init__ 中有一个接受了额外参数,另一个就会忽略多余参数(宽容机制)
  • 但自定义链中不要依赖这一行为,始终显式传递参数

五、__new__与__init_subclass__、__class_getitem__的关系

钩子触发时机典型用途
__new__每次实例化时控制实例创建
__init_subclass__定义子类时自动注册子类
__class_getitem__Foo[int] 语法泛型支持
元类 __new__定义类本身时修改类结构

总结

__new__ 的核心价值在于:在对象真正存在之前介入。当你需要控制的不是"对象初始化后的状态",而是"对象是哪个、是否创建、是什么类型"时,就该用 __new__。日常开发中最实用的三个场景是:单例、不可变类型继承、工厂方法

到此这篇关于Python 中 __new__的实现示例的文章就介绍到这了,更多相关Python __new__内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用Keras建立模型并训练等一系列操作方式

    使用Keras建立模型并训练等一系列操作方式

    这篇文章主要介绍了使用Keras建立模型并训练等一系列操作方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • Pandas 合并多个Dataframe(merge,concat)的方法

    Pandas 合并多个Dataframe(merge,concat)的方法

    今天小编就为大家分享一篇Pandas 合并多个Dataframe(merge,concat)的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-06-06
  • Flask添加路由的三种方法

    Flask添加路由的三种方法

    Flask 是一个流行的 Python Web 框架,它提供了多种方法来添加路由,本文详细的介绍了Flask添加路由的三种方法,感兴趣的可以了解一下
    2023-11-11
  • 利用python爬取古诗文网中各类古诗的方法

    利用python爬取古诗文网中各类古诗的方法

    这篇文章主要介绍了利用python爬取古诗文网中各类古诗的方法,文中通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-03-03
  • 模型训练时GPU利用率太低的原因及解决

    模型训练时GPU利用率太低的原因及解决

    这篇文章主要介绍了模型训练时GPU利用率太低的原因及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Django项目中实现使用qq第三方登录功能

    Django项目中实现使用qq第三方登录功能

    使用qq登录的前提是已经在qq互联官网创建网站应用并获取到QQ互联中网站应用的APP ID和APP KEY。这篇文章主要介绍了Django项目中实现使用qq第三方登录功能,需要的朋友可以参考下
    2019-08-08
  • Python如何检验样本是否服从正态分布

    Python如何检验样本是否服从正态分布

    这篇文章主要介绍了Python如何检验样本是否服从正态分布问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • python重写方法和重写特殊构造方法

    python重写方法和重写特殊构造方法

    这篇文章主要介绍了python重写方法和重写特殊构造方法,对于父类的方法,只要他不符合子类模拟的实物的行为,都可以进行重写,更多相关内容需要的朋友可以参考一下
    2022-07-07
  • Python3 hashlib 模块基本用法详解

    Python3 hashlib 模块基本用法详解

    在Python3中,hashlib模块提供了一系列加密哈希算法的实现,用于计算数据的哈希值,本文给大家介绍Python3 hashlib模块基本用法,感兴趣的朋友跟随小编一起看看吧
    2025-10-10
  • python接入使用百度翻译流程

    python接入使用百度翻译流程

    这篇文章主要介绍了利用Python接入百度翻译的实现方法,从而实现中英文互译的功能,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-07-07

最新评论