Python技术迷

__new__和__init__的区别。

先说结论:__new__ 是真正创建对象的,是类的构造器,而 __init__ 是初始化器,用来初始化这个刚造好的对象。

是不是有点拗口?我整点实打实的例子和段子给你解释明白 👇

说一个很经典的类比:

  • __new__ 就像你点了个外卖,商家开始做饭了,这是创建过程。
  • __init__ 是骑手把饭送到你手上,你打开包装加点辣条和酱油,这是初始化过程。

代码怎么写?👇

classDemo:
def__new__(cls, *args, **kwargs):
        print("执行 __new__ 方法")
        instance = super().__new__(cls)
return instance

def__init__(self, name):
        print("执行 __init__ 方法")
        self.name = name

obj = Demo("Python哥")

输出是这样的:

执行 __new__ 方法
执行 __init__ 方法

重点来了:__new__ 在对象还没生成之前调用,返回一个“空壳”;__init__ 是在壳子已经生成之后填充内容的。

那为啥我们平时几乎不重写 __new__ 呢?

因为 80% 的时候你用不到它。除非你搞的是:

  • 单例模式(必须确保全世界只能有一个对象)
  • 不同输入创建不同类型的对象(你搞点魔法方法逻辑)
  • 你继承了不可变类型,比如 int、str,必须用 __new__

比如说搞个单例:

classSingleton:
    _instance = None
def__new__(cls, *args, **kwargs):
if cls._instance isNone:
            cls._instance = super().__new__(cls)
return cls._instance

a = Singleton()
b = Singleton()
print(a is b)  # True,说明是同一个实例

这个场景下,不用 __new__ 你根本没法搞定。

如果你 __new__ 返回的不是当前类的实例,那 __init__ 根本不会被调用。

看看这个反例:

classTest:
def__new__(cls):
        print("new")
return"一个字符串"

def__init__(self):
        print("init")  # 不会执行

t = Test()
print(type(t))  # <class 'str'>

这玩意儿常被拿来出面试题,估计就是为了坑你一下 😅

还有种面试官的骚操作是:让你继承 int 搞个增强版整数类。

classMyInt(int):
def__new__(cls, value):
        print(f"new {value}")
return super().__new__(cls, value)

def__init__(self, value):
        print(f"init {value}")

a = MyInt(5)
print(a + 3)  # 8

这你就得知道,int 是不可变类型,想扩展只能靠 __new__,不然根本没机会修改对象本身。

说个真实项目踩过的坑。有一次我们搞一个 ORM 系统,模型类继承了 str,用来包一层带验证的字段。结果一个兄弟写了个验证逻辑放 __init__,然后死活不生效。为啥?因为 str 是不可变类型,它压根不调用 __init__。最后只能把逻辑塞到 __new__ 里才搞定。

总结一下:

  • __new__ 是用来“造对象”的,常见于不可变类型、自定义元类、单例;
  • __init__ 是用来“初始化对象”的,基本你每个类都会写;
  • 如果 __new__ 返回的不是实例,__init__ 不会执行;
  • 多数时候你用不到 __new__,除非你真想“搞点事”。

说实话,这玩意儿如果不是自己用到过,靠看文档记不住。最好的方式就是写几个奇怪的类,调试一遍你就彻底懂了。

最后送你一句话面试保命口诀:

new 是开模具,init 是组装件,搞清顺序别翻车,面试拿下不白练。

你要是再想挑战自己,研究下 metaclass 和 __call__,那才是 Python 黑魔法的最终形态,专治各种“我就想整点花的”。

-END-

我为大家打造了一份RPA教程,完全免费:https://www.songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领