编程学习网 > 编程语言 > Python > Python 的 __new__ 和 __init__ 到底有什么区别?
2026
07-06

Python 的 __new__ 和 __init__ 到底有什么区别?


很多学 Python 的朋友都会在类这里卡住,尤其是 __new__  __init__ 这两个方法。光看文档觉得挺绕,写代码又分不清该用哪个。今天咱们用大白话把这事说透。

先记一个核心:__new__ 管生,__init__ 管养。生就是创建对象,养就是给对象填属性。一个萝卜一个坑,各干各的活。

拿盖房子打个比方

把类想象成一张房子图纸。__new__ 就是施工队,负责把房子从无到有盖起来。房子盖好了,毛坯房一间。__init__ 是装修队,负责给房子刷墙铺地装家具。施工队不干活,装修队就没法进场。装修队干完了,房子才能住人。

代码里也是一样的道理。__new__ 先被调用,它返回一个实例对象。然后 Python 自动把这个对象传给 __init__,让 __init__ 给对象加属性。

先看一个最简单的例子

class House: 

   def __new__(cls, args, kwargs):

       print('施工队进场,造房子')

       instance = super().__new__(cls)

       return instance

   def __init__(self, color, rooms):

       print('装修队进场,开始装修')

       self.color = color

       self.rooms = rooms

house = House('白色', 3)

print(house.color)

运行结果会打印两行。第一行是施工队进场,造房子,第二行是装修队进场,开始装修。这就是调用顺序。你注意看,__new__ 的参数里有个 cls,它代表类本身。__init__ 的第一个参数是 self,就是 __new__ 返回的那个实例。

什么时候必须用 __new__

大部分场景你只需要写 __init__,但有两个情况你必须动 __new__。第一个是写单例模式,就是整个程序里某类只能有一个实例。第二个是继承不可变类型,比如 intstrtuple

咱们看单例模式的例子。

class SingleDog: 

   _instance = None

   def __new__(cls, args, kwargs):

       if cls._instance is None:

           cls._instance = super().__new__(cls)

       return cls._instance

   def __init__(self, name):

       self.name = name

dog1 = SingleDog('旺财')

dog2 = SingleDog('来福')

print(dog1 is dog2)   输出 True

print(dog1.name)      输出 '来福'

这个例子里 __new__ 在创建实例前先检查有没有现成的,有就直接返回旧的。所以 dog1 dog2 其实是同一个对象。你第二次传的参数来福把第一次的旺财覆盖了。这就是单例的特点。

再看继承不可变类型的例子。

class PositiveNumber(int): 

   def __new__(cls, value):

        if value < 0: 

           value = 0

       return super().__new__(cls, value)

n = PositiveNumber(-5)

print(n)   输出 0

int 是不可变类型,你没法在 __init__ 里改它的值,只能通过 __new__ 来控制创建时的值。

__new__ __init__ 的签名不同

__new__ 的第一个参数是类,后面可以跟任意参数。__init__ 的第一个参数是实例,后面参数要跟 __new__ 保持一致。Python 在调用 __new__ 时会把相同的参数传给 __init__。如果你在 __new__ 里改了参数,__init__ 接到的还是原来的值,不会跟着变。

一个容易搞混的点

有人以为 __init__ 可以代替 __new__,其实不行。如果你不写 __new__Python 会自动调用 object  __new__ 来创建实例。但如果你把 __new__ 写错了,比如忘了 return,那对象就创建失败,__init__ 根本不会执行。

记住一句话:__new__ 必须返回一个实例__init__ 不能返回任何值(只能返回 None)。这是规矩,破了就报错。

把两个方法一起写出花

你可以让 __new__ 返回一个完全不同的实例,比如返回一个缓存过的对象,或者根据条件返回不同的子类实例。这时候 __init__ 会在那个返回的实例上执行。

class Factory: 

   def __new__(cls, type):

       if type == 'A':

           return super().__new__(cls)

       elif type == 'B':

           return super().__new__(cls)

       else:

           return object.__new__(cls)

   def __init__(self, type):

       print(f'当前对象类型是 {type}')

f1 = Factory('A')

f2 = Factory('B')

你看,__new__ 虽然根据参数做了不同处理,但它返回的都是同一个类的实例,所以 __init__ 能被正确调用。如果 __new__ 返回了别的类的实例,__init__ 就压根不会跑。

实际开发怎么用

写普通业务代码,你基本只用 __init__ 给对象初始化属性就够了。只有涉及元类编程、单例模式、缓存对象池、或者扩展不可变类型时,才去碰 __new__。没必要为了炫技瞎用,容易把自己绕进去。

最后给你一个自查清单。如果你不确定该覆盖哪个方法,问自己两个问题。我要不要控制实例的创建过程,比如要不要只返回一个已有的对象,要不要改创建时的类型。如果要,就动 __new__。如果只是给建好的对象赋属性,那就只写 __init__

生和养,一个是构造函数一个是初始化函数。搞懂这个,你就不再迷糊了。

以上就是“Python 的 __new__ 和 __init__ 到底有什么区别?的详细内容,想要了解更多Python教程欢迎持续关注编程学习网。 

扫码二维码 获取免费视频学习资料

Python编程学习

查 看2022高级编程视频教程免费获取