Іноді тексти доводиться читати більше заради смаку ідеї, а не для деталей. Це один із таких випадків.
В пов'язаної сторінці , приклади 2.5, 2.6 і 2.7 повинні все використовувати один з методів, do_your_stuff
. (Тобто do_something
слід змінити на do_your_stuff
.)
Крім того, як зазначив Нед Дейлі , A.do_your_stuff
це повинен бути метод класу.
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
повертає зв'язаний метод (див. виноску 2 ). Оскільки cls
було передано як другий аргумент super()
, він cls
прив'язується до повернутого методу. Іншими словами, cls
передається як перший аргумент методу do_your_stuff()
класу А.
Повторимо ще раз: super(B, cls).do_your_stuff()
причини A
«и do_your_stuff
метод , який буде викликатися з cls
передається в якості першого аргументу. Для того, щоб це працювало, A
's
do_your_stuff
повинен бути методом класу. На пов’язаній сторінці про це не згадується, але це, безумовно, так.
PS. do_something = classmethod(do_something)
це старий спосіб створення методу класу. Новим (ер) способом є використання декоратора @classmethod.
Зверніть увагу, що super(B, cls)
не можна замінити на super(cls, cls)
. Це може призвести до нескінченних циклів. Наприклад,
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()
підніме RuntimeError: maximum recursion depth exceeded while calling a Python object
.
Якщо cls
є C
, то super(cls, cls)
пошук C.mro()
для класу , який приходить після C
.
In [161]: C.mro()
Out[161]: [__main__.C, __main__.B, __main__.A, object]
Оскільки цей клас B
, коли cls
є C
, super(cls, cls).do_your_stuff()
завжди дзвонить B.do_your_stuff
. Оскільки super(cls, cls).do_your_stuff()
викликається всередині B.do_your_stuff
, ви в кінцевому підсумку закликаєте B.do_your_stuff
в нескінченний цикл.
У Python3, то 0-аргумент формаsuper
була додана , щоб super(B, cls)
можна було б замінити super()
, і python3 буде з'ясувати з контексту , що super()
у визначенні class B
повинні бути еквівалентні super(B, cls)
.
Але ні за яких обставин ніколи super(cls, cls)
(або з подібних причин super(type(self), self)
) ніколи не є правильним.