Python:总是使用 __new__ 而不是 __init__?

Posted

技术标签:

【中文标题】Python:总是使用 __new__ 而不是 __init__?【英文标题】:Python: always use __new__ instead of __init__? 【发布时间】:2011-03-09 01:43:17 【问题描述】:

我了解__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 OO 的这一方面更适合我。

【问题讨论】:

关于该主题的旧问题:Python’s use of __new__ and __init__ ? why defined '__new__' and '__init__' all in a class的可能重复 【参考方案1】:

因此,类的类通常是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__(),除非你有特定的理由使用@ 987654331@.

【讨论】:

对我来说,这并不能真正回答 OP 的问题。您说“__init__() 可以做的事情是__new__() 可以做的事情的一个子集”,但这正是 OP 的重点,不是吗?如果这句话是真的,那么__init__() 可以安全地被弃用,因为它可以做的任何事情,__new__() 也可以做。 @Ray 你的结论不符合你的前提。虽然这句话表面上是正确的,__init__() 不能安全地弃用所有显而易见的原因 - 值得注意的是,(A) 需要保持与现有 Python 生态系统的向后兼容性 (B) __new__() API(其设计要求显式返回实例)与__init__() API(其设计没有施加此类约束)。 __new__() 会引发 API 违规,这很糟糕; __init__()没有,这很好。【参考方案2】:

guido's post 的一个可能答案(感谢@fraca7):

例如,在 pickle 模块中,__new__ 用于在反序列化对象时创建实例。在这种情况下,会创建实例,但不会调用 __init__ 方法。

还有其他类似的答案吗?


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

我想知道是否有什么__init__ 可以做到__new__ 不能做到?

是的,与__new__ 不同,您在__init__ 方法中放置的操作不会在解酸过程中执行。 __new__ 无法区分。

【讨论】:

【参考方案3】:

嗯,在谷歌上寻找__new__ vs __init__ 显示this。

长话短说,__new__ 返回一个新的对象实例,而__init__ 什么也不返回,只是初始化类成员。

编辑:要真正回答您的问题,您永远不需要覆盖 __new__,除非您是不可变类型的子类。

【讨论】:

Guido 最近谈到了这个:python-history.blogspot.com/2010/06/… 还有其他原因使用__new__,例如享元模式。

以上是关于Python:总是使用 __new__ 而不是 __init__?的主要内容,如果未能解决你的问题,请参考以下文章

__new__ 和 __init__ [重复]

Python类中的__new__和__init__的区别

python之路——28

详解Python中的__new__、__init__、__call__三个特殊方法

[译]为什么在__new __()后总是调用__init __()?

Python常用内建方法:__init__,__new__,__class__的理解