我到处看到的例子是超一流的方法应该由被称为:Python的超级方法调用替代
super(SuperClass, instance).method(args)
是否有任何缺点做:
SuperClass.method(instance, args)
我到处看到的例子是超一流的方法应该由被称为:Python的超级方法调用替代
super(SuperClass, instance).method(args)
是否有任何缺点做:
SuperClass.method(instance, args)
考虑以下情况:
class A(object):
def __init__(self):
print('Running A.__init__')
super(A,self).__init__()
class B(A):
def __init__(self):
print('Running B.__init__')
# super(B,self).__init__()
A.__init__(self)
class C(A):
def __init__(self):
print('Running C.__init__')
super(C,self).__init__()
class D(B,C):
def __init__(self):
print('Running D.__init__')
super(D,self).__init__()
foo=D()
因此类形成所谓的继承钻石:
A
/\
B C
\/
D
运行代码产量
Running D.__init__
Running B.__init__
Running A.__init__
这是不好的,因为C
“ s跳过了__init__
。原因是因为B
的__init__
直接调用A
的__init__
。
super
的用途是解决继承钻石。如果您取消注释
# super(B,self).__init__()
和注释掉
A.__init__(self)
代码产生了更多desireable结果:
Running D.__init__
Running B.__init__
Running C.__init__
Running A.__init__
现在所有的__init__
方法被调用。请注意,在您定义B.__init__
时,您可能会认为认为 0123'与呼叫A.__init__(self)
相同,但您会错误的。在上述情况下,super(B,self).__init__()
实际上调用C.__init__(self)
。
圣烟,B
一无所知C
,然而super(B,self)
知道调用C
的__init__
?原因是因为self.__class__.mro()
包含C
。换句话说,self
(或上面的foo
)知道约C
。
所以要小心 - 两者不可互换。他们可以产生截然不同的结果。
使用super
has pitfalls.在继承关系图中的所有类之间需要相当程度的协调。 (他们必须,例如,或者具有相同的调用签名为__init__
,因为任何特定__init__
不知道其他__init__
super
下一步可能调用,或其他 use **kwargs
)。此外,你必须是有关使用super
到处是一致的。跳过一次(如上面的例子),你击败了super
的整个目的。 查看更多陷阱的链接。
如果您完全控制了您的类层次结构,或者避免了继承菱形,那么不需要super
。
有没有处罚的,是,尽管你的例子有些误导。在第一个例子,它应该是
super(SubClass, instance).method(args) # Sub, not SuperClass
,并导致我引用了Python docs:
有两个典型的用例
super
的。在具有单一继承的类层次结构中,可以使用super
来引用父类而不显式命名它们,从而使代码更易于维护。这种用法与其他编程语言中使用的super
非常类似。第二个用例是在动态执行环境中支持协作多重继承。这个用例是Python独有的,在静态编译的语言或仅支持单一继承的语言中找不到。这使得在多个基类实现相同方法的情况下实现“菱形图”成为可能。良好的设计规定,这种方法在每种情况下都具有相同的调用签名(因为调用顺序是在运行时确定的,因为该顺序适用于类层次结构中的更改,并且因为该顺序可以包含运行时未知的同级类)。
基本上,使用第一种方法,你不要使用有硬编码的父类中有单级的层次,你根本就没有真正做你想做的(有效/有效)使用多重继承时的第二种方法。
我是否理解正确,在单一继承情况下没有使用`超级`的缺点? – Wolf 2015-02-02 10:08:41
+1为超级有害链接。我即将自己发布。 – 2011-02-17 20:47:59