Manchmal müssen Texte eher für den Geschmack der Idee als für die Details gelesen werden. Dies ist einer dieser Fälle.
Auf der verlinkten Seite sollten die Beispiele 2.5, 2.6 und 2.7 alle eine Methode verwenden do_your_stuff
. (Das heißt, do_something
sollte geändert werden do_your_stuff
.)
Darüber hinaus muss, wie Ned Deily betonte , A.do_your_stuff
eine Klassenmethode sein.
class A(object):
@classmethod
def do_your_stuff(cls):
print 'This is A'
class B(A):
@classmethod
def do_your_stuff(cls):
super(B, cls).do_your_stuff()
B.do_your_stuff()
super(B, cls).do_your_stuff
gibt eine gebundene Methode zurück (siehe Fußnote 2 ). Da cls
als zweites Argument an übergeben wurde super()
, wird es cls
an die zurückgegebene Methode gebunden. Mit anderen Worten, cls
wird als erstes Argument an die Methode do_your_stuff()
der Klasse A übergeben.
Um es noch einmal zu wiederholen: Bewirkt, super(B, cls).do_your_stuff()
dass A
die do_your_stuff
Methode von aufgerufen wird, wobei cls
als erstes Argument übergeben wird. Damit das funktioniert, muss A
's
do_your_stuff
eine Klassenmethode sein. Die verlinkte Seite erwähnt das nicht, aber das ist definitiv der Fall.
PS. do_something = classmethod(do_something)
ist die alte Art, eine Klassenmethode zu erstellen. Die neue (er) Möglichkeit besteht darin, den @ classmethod-Dekorator zu verwenden.
Beachten Sie, dass super(B, cls)
nicht durch ersetzt werden kann super(cls, cls)
. Dies könnte zu Endlosschleifen führen. Zum Beispiel,
class A(object):
@classmethod
def do_your_stuff(cls):
print('This is A')
class B(A):
@classmethod
def do_your_stuff(cls):
print('This is B')
super(cls, cls).do_your_stuff()
class C(B):
@classmethod
def do_your_stuff(cls):
print('This is C')
super(cls, cls).do_your_stuff()
C.do_your_stuff()
wird erhöhen RuntimeError: maximum recursion depth exceeded while calling a Python object
.
Wenn cls
ist C
, dann super(cls, cls)
sucht C.mro()
für die Klasse , die nach kommt C
.
In [161]: C.mro()
Out[161]: [__main__.C, __main__.B, __main__.A, object]
Da diese Klasse B
, wann cls
ist C
, super(cls, cls).do_your_stuff()
immer aufruft B.do_your_stuff
. Da super(cls, cls).do_your_stuff()
innen aufgerufen wird B.do_your_stuff
, rufen Sie am Ende B.do_your_stuff
in einer Endlosschleife auf.
In Python3 wurde die 0-Argument-Form vonsuper
hinzugefügt, damit super(B, cls)
sie durch ersetzt werden kann super()
, und Python3 wird aus dem Kontext herausfinden, dass super()
in der Definition von class B
gleich sein sollte super(B, cls)
.
Aber unter keinen Umständen ist super(cls, cls)
(oder aus ähnlichen Gründen super(type(self), self)
) jemals richtig.