Иногда тексты нужно читать больше из-за изюминки идеи, а не из-за деталей. Это один из таких случаев.
В связанной странице , примеры 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()класса A.
Повторим еще раз: super(B, cls).do_your_stuff()причины A«ы do_your_stuffметод , который будет вызываться с clsпередается в качестве первого аргумента. Для того , чтобы работать, A«s
do_your_stuffдолжен быть метод класса. На связанной странице это не упоминается, но это определенно так.
PS. do_something = classmethod(do_something)это старый способ создания classmethod. Новый (er) способ - использовать декоратор @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)) никогда не является правильным.