我到處看到的例子是超一流的方法應該由被稱爲: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