← 返回题目列表

Python 中 __new__ 和 __init__ 有什么区别?

高频 中等 第 10 / 21 题 更新于 2026/07/27
__new____init__对象创建初始化

简化版

__new__ 负责创建对象,返回实例;__init__ 负责初始化对象,给已经创建好的实例设置属性。正常业务类主要重写 __init__,只有控制对象创建过程、不可变类型子类化、单例等场景才常重写 __new__

详细版

对象创建大致分两步:

obj = ClassName(...)

背后会先调用:

obj = ClassName.__new__(ClassName, ...)

如果 __new__ 返回的是当前类的实例,再调用:

ClassName.__init__(obj, ...)

示例:

class User:
    def __new__(cls, *args, **kwargs):
        print("__new__")
        return super().__new__(cls)

    def __init__(self, name):
        print("__init__")
        self.name = name

u = User("Tom")

输出顺序是:

__new__
__init__

__new__ 是静态创建阶段方法,第一个参数通常叫 cls__init__ 是实例初始化方法,第一个参数是 self

完整版教学

一、对象不是 init 创建出来的

很多人以为 __init__ 是构造方法,负责创建对象。更准确地说,__init__ 是初始化方法,对象在进入 __init__ 前已经存在。

class User:
    def __init__(self, name):
        self.name = name

这里的 self 就是已经创建好的实例。__init__ 做的事情是给它挂属性、校验参数、准备初始状态。

真正控制对象创建的是 __new__

class User:
    def __new__(cls, *args, **kwargs):
        return super().__new__(cls)

它必须返回一个对象。

二、调用流程怎么走

执行:

u = User("Tom")

可以粗略理解为:

tmp = User.__new__(User, "Tom")
if isinstance(tmp, User):
    User.__init__(tmp, "Tom")
u = tmp

如果 __new__ 返回的不是当前类实例,__init__ 可能不会按普通流程执行。

例如:

class A:
    def __new__(cls):
        return "not an A"

    def __init__(self):
        print("init")

a = A()
print(a)  # not an A

这里返回的是字符串,不是 A 的实例,所以 A.__init__ 不会用这个字符串当 self 去初始化。

三、为什么平时很少写 new

大多数业务类不需要控制对象分配过程,只需要初始化属性:

class Order:
    def __init__(self, order_id, amount):
        self.order_id = order_id
        self.amount = amount

这种场景重写 __init__ 就够了。

随意重写 __new__ 会让对象创建过程变复杂,也容易影响继承链。

四、哪些场景会用 new

常见场景有三个。

第一,不可变类型子类化。比如继承 tuplestrint,对象一旦创建就不能再改内部值,所以要在 __new__ 阶段决定值:

class UpperStr(str):
    def __new__(cls, value):
        return super().__new__(cls, value.upper())

s = UpperStr("python")
print(s)  # PYTHON

第二,单例控制:

class Singleton:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

第三,框架或底层库需要定制对象创建流程。

五、init 是否可以返回值

__init__ 不能返回非 None 值。

错误示例:

class User:
    def __init__(self):
        return self

这会报错,因为 __init__ 的职责是初始化,不是返回对象。对象已经由 __new__ 返回了。

六、继承中要注意 super

如果你重写 __new__,通常要调用父类的 __new__

def __new__(cls, *args, **kwargs):
    return super().__new__(cls)

如果你重写 __init__,也常需要调用父类初始化:

class Base:
    def __init__(self, name):
        self.name = name

class Child(Base):
    def __init__(self, name, age):
        super().__init__(name)
        self.age = age

否则父类中定义的属性可能没有被初始化。

七、常见误区与追问

易错点:__new__ 管“有没有对象、返回哪个对象”,__init__ 管“拿到对象后怎么填属性”。把这条线分清,单例、不可变对象、自定义创建流程都好解释。

  • 误区:__init__ 是构造函数,负责创建对象。 更准确地说,__new__ 创建并返回实例,__init__ 初始化这个已经创建好的实例;Python 里二者职责不同。
  • 追问:__init__ 能不能返回对象? 不能,__init__ 必须返回 None;如果返回其他值会抛 TypeError,因为对象已经由 __new__ 返回了。
  • 误区:所有类都应该重写 __new__ 大多数业务类只需要 __init__;只有要控制实例创建、缓存实例、单例、不可变类型子类化时,才考虑 __new__
  • 追问:为什么继承 tuplestr 这类不可变类型时常用 __new__ 不可变对象内容在创建时就要确定,等到 __init__ 阶段已经无法原地改内部值,所以要在 __new__ 里把值传给父类创建过程。
  • 误区:__new__ 一定会触发 __init__ 如果 __new__ 返回的不是当前类的实例,Python 不会按当前类继续调用 __init__;这也是它能深度控制对象创建的原因。
  • 追问:单例为什么常在 __new__ 里实现? 因为单例要控制“返回哪个实例”,这是创建阶段职责;但工程中还要注意线程安全和重复调用 __init__ 造成状态被覆盖。

八、加强记忆

__new__ 创建对象,__init__ 初始化对象。平时写类主要写 __init__;只有要干预“对象怎么被造出来”时才考虑 __new__。判断两者最简单的方法是看返回值:__new__ 必须返回实例,__init__ 只能返回 None