为什么__new__和__init__在挑选超类时表现得有所不同?

时间:2016-07-04 23:24:28

标签: python python-3.x

我在阅读有关元类here时遇到以下代码,虽然我不知道这种区别是否特定于元类,我怀疑它不是:

class MetaBase(type):
    def __new__(mcl, name, bases, nmspc):
        print('MetaBase.__new__\n')
        return super(MetaBase, mcl).__new__(mcl, name, bases, nmspc)

    def __init__(cls, name, bases, nmspc):
        print('MetaBase.__init__\n')
        super(MetaBase, cls).__init__(name, bases, nmspc)

请注意,super().__init__()调用省略了第一个参数。我猜它是隐式传递的,因为它在super()返回的任何类上调用一个方法。这就是我通常看到这样的调用构建的方式,尽管它们通常涉及self正常类而不是元类上的cls / mcl。

super().__new__()调用明确地传递了mcl。我不明白为什么。签名看起来和我一样。

我很困惑。是super()在每种情况下都会返回不同的东西吗?这里发生了什么,在推翻其他魔术方法时,我是否应该被这种方法所困扰?

[编辑:有人建议这是this question的副本,它描述了它们的不同功能。虽然在那里的一些例子中表现出相同的差异,但我没有看到它存在的原因或它是__new__的独特之处。]

1 个答案:

答案 0 :(得分:1)

  

super().__ new __()调用明确地传递了mcl。我不   明白为什么。签名看起来和我一样。

__new__方法是一个奇怪的方法,因为它是一个静态方法,但是特殊的方法,所以你不必这样声明它。作为static方法意味着您必须显式传入所需的任何变量(在本例中为元类)。

相比之下,__init__就像任何其他常规方法一样。从实例查找时,实例将自动作为第一个参数传入。无论您是使用cls.__init__(name, bases, nmspc)直接调用父级,还是使用带有super(MetaBase, cls).__init__(name, bases, nmspc) super(),这都有效。这两个都作为第一个参数传入 cls 。这就是绑定方法如何适用于普通类和元类。 super()是否被使用并不重要。

所以,奇怪的一个案例是__new__,因为它是staticmethod,根据定义,它没有自动的前置行为。

  当我压倒其他魔法时,我是否应该被这个咬伤?   方法

静态方法有点罕见。在魔术方法中,__new__是我唯一能想到的。所以,你应该是安全的: - )