Новое магическое 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