Czasami teksty trzeba czytać bardziej ze względu na smak pomysłu niż szczegóły. To jest jeden z tych przypadków.
Na stronie , do której prowadzi łącze, w przykładach 2.5, 2.6 i 2.7 należy używać jednej metody, czyli do_your_stuff
. (Oznacza to, że do_something
należy zmienić na do_your_stuff
.)
Ponadto, jak zauważył Ned Deily , A.do_your_stuff
musi to być metoda klasowa.
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
zwraca powiązaną metodę (patrz przypis 2 ). Ponieważ cls
został przekazany jako drugi argument do super()
, jest cls
on powiązany z zwróconą metodą. Innymi słowy, cls
zostaje przekazany jako pierwszy argument do metody do_your_stuff()
klasy A.
Powtórzmy: super(B, cls).do_your_stuff()
przyczyny A
„s do_your_stuff
metodę można nazwać z cls
przekazywany jako pierwszy argument. Aby to do pracy, A
„s
do_your_stuff
musi być metoda klasy. Strona, do której prowadzi link, o tym nie wspomina, ale ostatecznie tak jest.
PS. do_something = classmethod(do_something)
jest starym sposobem tworzenia metody klasowej. Nowym (nowym) sposobem jest użycie dekoratora @classmethod.
Pamiętaj, że super(B, cls)
nie można tego zastąpić super(cls, cls)
. Może to prowadzić do nieskończonych pętli. Na przykład,
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()
wzrośnie RuntimeError: maximum recursion depth exceeded while calling a Python object
.
Jeśli cls
tak C
, super(cls, cls)
wyszukuje następną C.mro()
klasę C
.
In [161]: C.mro()
Out[161]: [__main__.C, __main__.B, __main__.A, object]
Ponieważ ta klasa jest B
, kiedy cls
jest C
, super(cls, cls).do_your_stuff()
zawsze dzwoni B.do_your_stuff
. Ponieważ super(cls, cls).do_your_stuff()
jest wywoływany wewnątrz B.do_your_stuff
, w końcu wywołujesz B.do_your_stuff
w nieskończonej pętli.
W Pythonie3 została dodana 0-argumentowa forma argumentu,super
więc super(B, cls)
można ją zastąpić super()
, a Python3 wykryje z kontekstu, który super()
w definicji class B
powinien być równoważny super(B, cls)
.
Ale w żadnym wypadku nie jest super(cls, cls)
(ani z podobnych powodów super(type(self), self)
) nigdy nie jest poprawne.