我在阅读有关元类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__
的独特之处。]
答案 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__
是我唯一能想到的。所以,你应该是安全的: - )