Подтвердить что ты не робот

Python super() аргументы: почему бы не super (obj)?

Я пытаюсь понять, когда и как правильно использовать super() в Python (либо 2.7.x, либо 3.x)

on >>> help(super) интерпретатор говорит мне, как его называть:

class super(object)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)

Я понимаю, что в Python3.x теперь можно juse использовать super() в определении класса, но я не понимаю, почему super(obj) невозможно. Или super(self) в определении класса.

Я знаю, что для этого должна быть причина, но я не могу ее найти. Для меня эти строки эквивалентны super(obj.__class__, obj) или super(self.__class__, self), и они будут работать правильно?

Я бы подумал, что просто набрав super(obj) будет хорошим ярлыком даже в Python 3.x.

4b9b3361

Ответ 1

Форма с двумя аргументами нужна только в Python 2. Причина в том, что self.__class__ всегда ссылается на класс "leaf" в дереве наследования - то есть на самом конкретном классе объекта, но когда вы вызываете super, вам нужно указать, какая реализация в настоящее время вызывается, поэтому она может вызывать следующую в дереве наследования.

Предположим, что у вас есть:

class A(object):
   def foo(self):
      pass

class B(A):
   def foo(self):
      super(self.__class__, self).foo()

class C(B):
   def foo(self):
      super(self.__class__, self).foo()

c = C()

Обратите внимание, что c.__class__ всегда C. Теперь подумайте, что произойдет, если вы вызываете c.foo().

Когда вы вызываете super(self.__class__, self) в методе C, он будет похож на вызов super(C, self), что означает "вызывать версию этого метода, унаследованного C". Это вызовет B.foo, что хорошо. Но когда вы вызываете super(self.__class__, self) из B, ему все равно нравится называть super(C, self), потому что он тот же self, поэтому self.__class__ по-прежнему C. В результате вызов в B снова вызовет B.foo и произойдет бесконечная рекурсия.

Конечно, то, что вы действительно хотите, это вызов super(classThatDefinedTheImplementationThatIsCurrentlyExecuting, self), и это действительно то, что делает Python 3 super().

В Python 3 вы можете просто сделать super().foo(), и он поступает правильно. Мне непонятно, что вы имеете в виду super(self) как ярлык. В Python 2 это не работает по причине, описанной выше. В Python 3 это будет "longcut", потому что вы можете просто использовать простой super().

Использование методов super(type) и super(type1, type2) иногда может потребоваться в Python 3, но для необычных ситуаций они всегда были более эзотерическими.

Ответ 2

Попытка короткого ответа:

self.__class__ всегда является фактическим ( "самым большим" ) классом вашего экземпляра объекта - не обязательно желаемым классом, который реализует функцию!

Замените super(self.__class__, self) на super(__class__, self), и вы правы в определении метода в Python 3, потому что Python 3 предоставляет переменную magic cell __class__ для класса реализации.

И просто super() с нулевыми аргументами уже является ярлыком для super(__class__, self) в Python 3. См. PEP3135.

Python 2 не знает __class__ и ярлык с нулевым аргументом super().