以下是我的代码的两个版本:
非工作
class A:
def __init__(self):
print "I am A "
class B:
def __init__(self):
print "I am B "
class C(A, B):
def __init__(self):
super(C, self).__init__()
c = C()
这引发了例外:
super(C, self).__init__()
TypeError: must be type, not classobj
工作版
class A(object):
def __init__(self):
print "I am A "
class B:
def __init__(self):
print "I am B "
class C(A, B):
def __init__(self):
super(C, self).__init__()
c = C()
如果其中一个父类明确地继承了 object ,则没有异常,并且事情可以按预期工作。任何解释,为什么?
使用上面的工作,它打印“我是A”而不是“我是B”,这意味着它只初始化A类,而不是B类。初始化子级中的多个父类类?
答案 0 :(得分:5)
那是因为super
仅适用于新式类(继承自object
)。在Python 2中,object
在继承层次结构中没有的类(如第一个示例)称为旧式类,不应在任何地方使用。
这是一个古老的历史文物,从Python第一次添加OO开始,开发人员就错了。除此之外,新式类允许使用super
,描述符协议(属性),并对多重继承的处理方式进行了一些修复。 super
是其中之一,但最重要的是为钻石继承案例计算方法解析顺序的方式(A继承自B和C,它们都从D继承)。在此处阅读更多相关信息:http://python-history.blogspot.fr/2010/06/method-resolution-order.html
请注意,Python 3完全抛弃了旧式类,因此在Python 3中,所有类都是新式类,并且继承自对象,无论它们是否明确地执行。
答案 1 :(得分:2)
super()仅适用于新式类(任何继承自object的类)。因此,您无法将类对象传递给super
。
super有两个典型的用例。在具有单继承的类层次结构中,super可用于引用父类而不显式命名它们,从而使代码更易于维护。这种用法与其他编程语言中super的使用密切相关。
第二个用例是在动态执行环境中支持协作多重继承。此用例是Python独有的,在静态编译语言或仅支持单继承的语言中找不到。这使得实现“菱形图”成为可能,其中多个基类实现相同的方法。好的设计要求此方法在每种情况下都具有相同的调用签名(因为调用的顺序是在运行时确定的,因为该顺序适应类层次结构中的更改,并且因为该顺序可以包括在运行时之前未知的兄弟类)。
典型的超类调用如下所示:
class C(B):
def method(self, arg):
super(C, self).method(arg)