Python: 什么时候总是使用 __new__ 而非 __init__?

29 投票
3 回答
5660 浏览
提问于 2025-04-16 00:31

我明白__init____new__是怎么工作的。现在我想知道,__init__有没有什么是__new__做不到的呢?

也就是说,是否可以用下面的方式来替代__init__

class MySubclass(object):
    def __new__(cls, *args, **kwargs):
        self = super(MySubclass, cls).__new__(cls, *args, **kwargs)
        // Do __init__ stuff here
        return self

我问这个问题是因为我想更好地理解Python的面向对象编程。

3 个回答

2

好吧,我在谷歌上搜索了 __new__ vs __init__,找到了这个链接

简单来说,__new__ 是用来创建一个新的对象实例的,而 __init__ 则什么都不返回,它只是用来初始化类的成员。

补充一下:其实要回答你的问题,除非你在继承一些不可变类型,否则你通常不需要重写 __new__

24

所以,一个类的类型通常是 type,当你调用 Class() 时,实际上是 Class 的类里的 __call__() 方法在处理这个调用。我觉得 type.__call__() 的实现大概是这样的:

def __call__(cls, *args, **kwargs):
    # should do the same thing as type.__call__
    obj = cls.__new__(cls, *args, **kwargs)
    if isinstance(obj, cls):
        obj.__init__(*args, **kwargs)
    return obj

直接回答你的问题是,不,__init__() 能做的事情(改变或“初始化”一个特定的实例)只是 __new__() 能做的事情(创建或选择任何它想要的对象,在返回这个对象之前对它做任何事情)的一个子集。

不过,有这两个方法可用是很方便的。使用 __init__() 更简单(它不需要创建任何东西,也不需要返回任何东西),我认为最好是总是使用 __init__(),除非你有特别的理由去使用 __new__()

4

这是来自guido的帖子的一个可能答案(感谢@fraca7):

举个例子,在pickle模块中,__new__用于在反序列化对象时创建实例。在这种情况下,实例被创建了,但__init__方法并没有被调用。

还有其他类似的答案吗?


我接受这个答案作为对我自己问题的“是”的回答:

我在想,__init__能做的事情,有没有是__new__做不到的?

是的,不像__new__,你在__init__方法中写的操作在反序列化过程中不会被执行。__new__无法区分这一点。

撰写回答