Новое магическое super()поведение было добавлено, чтобы избежать нарушения принципа СУХОЙ (не повторять себя), см. PEP 3135 . Необходимость явного присвоения имени классу, ссылаясь на него как на глобальный, также подвержена тем же проблемам перепривязки, которые вы обнаружили для super()себя:
class Foo(Bar):
def baz(self):
return super(Foo, self).baz() + 42
Spam = Foo
Foo = something_else()
Spam().baz() # liable to blow up
То же самое относится к использованию декораторов классов, где декоратор возвращает новый объект, который связывает имя класса:
@class_decorator_returning_new_class
class Foo(Bar):
def baz(self):
# Now `Foo` is a *different class*
return super(Foo, self).baz() + 42
Волшебная super() __class__ячейка прекрасно обходит эти проблемы, предоставляя вам доступ к исходному объекту класса.
PEP был запущен Гвидо, который первоначально предполагал superстать ключевым словом , и идея использовать ячейку для поиска текущего класса была также его . Конечно, идея сделать это ключевым словом была частью первого проекта PEP .
Однако на самом деле сам Гвидо отошел от идеи ключевого слова как «слишком волшебной» , предложив вместо этого текущую реализацию. Он ожидал, что использование другого имени для super()может быть проблемой :
Мой патч использует промежуточное решение: оно предполагает, что вам нужно __class__
всякий раз, когда вы используете переменную с именем 'super'. Таким образом, если вы (глобально) переименовать superв supperи использования , supperно не super, это не будет работать без аргументов (но это все равно будет работать , если вы передадите его либо
__class__или фактический объект класса); если у вас есть не связанная переменная с именем super, все будет работать, но метод будет использовать немного более медленный путь вызова, используемый для переменных ячейки.
Итак, в конце концов, это был сам Гвидо, который заявил, что использование superключевого слова не является правильным, и что предоставление магической __class__ячейки было приемлемым компромиссом.
Я согласен с тем, что магическое, неявное поведение реализации несколько удивительно, но super()является одной из наиболее неправильно примененных функций в языке. Просто взгляните на все неправильные обращения super(type(self), self)или super(self.__class__, self)обращения, найденные в Интернете; если какой-либо из этого кода будет вызван из производного класса, вы получите исключение бесконечной рекурсии . По крайней мере, упрощенный super()вызов без аргументов позволяет избежать этой проблемы.
Что касается переименованных super_; просто ссылаться __class__на ваш метод , а также , и он будет работать снова. Ячейка создается, если вы ссылаетесь на имена super или __class__ в вашем методе:
>>> super_ = super
>>> class A(object):
... def x(self):
... print("No flipping")
...
>>> class B(A):
... def x(self):
... __class__ # just referencing it is enough
... super_().x()
...
>>> B().x()
No flipping