为什么python的super不只接受实例?
在 Python 2.x 中,super 有以下几种用法:
class super(object)
| super(type) -> unbound super object
| super(type, obj) -> bound super object; requires isinstance(obj, type)
| super(type, type2) -> bound super object; requires issubclass(type2, type)
| Typical use to call a cooperative superclass method:
据我所知,super 是一个类,它把类型和(最终)实例包裹起来,以便找到一个类的父类。
我有几个地方感到困惑:
- 为什么没有
super(instance)
这种用法?通常我们会用super(self).__init__()
。从技术上讲,你可以通过对象本身获取它的类型,所以现在的用法super(ClassType, self).__init__()
有点多余。我猜这可能是为了兼容旧式类或者处理多重继承,但我想听听你的看法。 - 另一方面,为什么 Python 3 会接受
super().__init__()
这种写法?我觉得这有点神奇,似乎违背了“显式优于隐式”的原则。我觉得用self.super().__init__()
会更合适。
2 个回答
我不能给出具体的答案,但你有没有看过关于super关键字的PEP文档?我快速搜索了一下,找到了PEP 367和PEP 3135。
http://www.python.org/dev/peps/pep-0367/
http://www.python.org/dev/peps/pep-3135/#numbering-note
与我知道的其他语言不同的是,通常你可以在PEP文档中找到Python的一些特殊用法的答案,还有清晰的解释和立场说明。
更新:
看完了3135和相关的Python邮件列表以及语言参考文档后,我大致明白了为什么Python 2和Python 3在这方面的不同。
http://docs.python.org/library/functions.html?highlight=super#super
我觉得super这个功能的设计是为了让事情变得明确和冗余,这样可以更安全,并且保持逻辑尽可能简单(没有复杂的逻辑去寻找父类)。因为super是一个内置函数,它必须根据提供的信息推断出正确的返回值,而不增加Python对象结构的复杂性。
PEP 3135改变了一切,因为它提出并赢得了一个关于让super更简洁的论点。
super(ClassType, self).__init__()
在多重继承的情况下并不是多余的——ClassType
不一定是 self
的类型,而是你想要调用的那个类的名字,用来进行合作调用 __init__
方法。
在类的继承关系中,比如 C 继承 B 继承 A
,在 C.__init__
中,你想从 C
的角度调用父类的初始化方法,所以你会调用 B.__init__
;然后在 B.__init__
中,你必须把类类型 B
传给 super——因为你想要解决 B
的父类调用(或者说,C
的方法解析顺序中 B
之后的下一个类)。
class A (object):
def __init__(self):
pass
class B (A):
def __init__(self):
super(B, self).__init__()
class C (B):
def __init__(self):
super(C, self).__init__()
如果你现在创建一个实例 c = C()
,你会发现类类型并不是多余的——在 B.__init__
中使用 super(self).__init__()
实际上是行不通的!你需要手动指定调用 super 的方法所在的类(在 Python 3 中,这个问题通过一个指向方法所在类的隐藏变量来解决)。
这里有两个关于 super 和多重继承的示例链接: