【发布时间】:2019-09-21 19:41:09
【问题描述】:
何时(以及为什么)引入 Python __new__() 函数?
创建一个类的实例分为三个步骤,例如MyClass():
-
MyClass.__call__()被调用。此方法必须在MyClass的元类中定义。 -
MyClass.__new__()被调用(由__call__)。在MyClass本身上定义。这将创建实例。 -
MyClass.__init__()被调用(也被__call__调用)。这会初始化实例。
实例的创建可能会受到重载__call__ 或__new__ 的影响。通常没有理由重载__call__ 而不是__new__(例如Using the __call__ method of a metaclass instead of __new__?)。
我们有一些旧代码(仍然运行良好!)其中__call__ 被重载。给出的原因是 __new__ 当时不可用。所以我试图了解更多关于 Python 和我们的代码的历史,但我无法弄清楚 __new__ 是什么时候引入的。
__new__ 出现在documentation for Python 2.4 中,而不出现在Python 2.3 中,但它没有出现在任何 Python 2 版本的 whathsnew 中。我能找到的first commit that introduced __new__(将descr-branch 合并回主干。)是从2001 年开始的,但是“返回主干”消息表明以前有过一些东西。几个月前的PEP 252 (Making Types Look More Like Classes) 和PEP 253 (Subtyping Built-in Types) 似乎是相关的。
了解更多关于 __new__ 的介绍将让我们更多地了解 Python 为何如此。
编辑澄清:
似乎class.__new__ 复制了metaclass.__call__ 已经提供的功能。添加一个方法只是为了以更好的方式复制现有功能似乎不符合 Pythonic。
__new__ 是为数不多的开箱即用的类方法之一(即使用cls 作为第一个参数),从而引入了以前不存在的复杂性。如果类是函数的第一个参数,那么可以认为该函数应该是元类的普通方法。但该方法确实已经存在:__call__()。我觉得我错过了什么。
应该有一种——最好只有一种——明显的方法。
【问题讨论】:
-
您说引入
__new__违反了“应该有一种——最好只有一种——明显的方式来做到这一点”的规则。来自 Python 之禅。但还有一个:“虽然实用胜过纯洁。”。引入一种更易于编写、更易于阅读且不需要您编写元类的方法是一个实际的决定,它超越了“一种方法”的纯粹性。这就是为什么我可以说拥有__new__是Pythonic。 -
这只是@Sanyash,'实用胜于纯粹'?我不太相信额外的复杂性实际上会使事情变得更加实用。
__new__确实允许人们在不实际使用元类的情况下做元类的东西。不过不确定是否值得:当您使用__new__时,您已经深入了解了,因此您不妨直接使用元类。不过你可能是对的。 -
@BlackShift:在答案中添加了对您的编辑的回复。
-
我看到the documentation of Python 2.2中提到的
__new__,是引入新式类的版本。
标签: python oop python-2.x