Прочитав о super() object в Python, я прочитал следующее утверждение:
Если второй аргумент опущен, вернувшийся объект возвращается unbound
Что это значит, и как я могу использовать super() с одним аргументом в коде?
Прочитав о super() object в Python, я прочитал следующее утверждение:
Если второй аргумент опущен, вернувшийся объект возвращается unbound
Что это значит, и как я могу использовать super() с одним аргументом в коде?
Функциональные объекты Python являются дескрипторами, а Python использует протокол дескриптора для привязки функций к экземпляру. Этот процесс производит связанный метод.
Привязка - это то, что заставляет "магический" self аргумент появляться, когда вы вызываете метод, и то, что заставляет объект property автоматически вызывать методы, когда вы пытаетесь использовать свойство как атрибут в экземплярах.
super() с двумя аргументами вызывает тот же протокол дескриптора, когда вы пытаетесь использовать его для поиска методов в родительских классах; super(Foo, self).bar() будет проходить родительские классы Foo до тех пор, пока не будет найдена bar атрибута, и если это объект, являющийся дескриптором, он будет привязан к self. Вызов bar затем вызывает связанный метод, который в свою очередь вызывает функцию, передающую аргумент self как bar(self).
Для этого объект super() хранит класс (первый аргумент) и self (второй аргумент) для привязки, а также тип аргумента self в качестве атрибутов __thisclass__, __self__ и __self_class__ соответственно:
>>> class Foo:
... def bar(self):
... return 'bar on Foo'
...
>>> class Spam(Foo):
... def bar(self):
... return 'bar on Spam'
...
>>> spam = Spam()
>>> super(Spam, spam)
<super: <class 'Spam'>, <Spam object>>
>>> super(Spam, spam).__thisclass__
<class '__main__.Spam'>
>>> super(Spam, spam).__self__
<__main__.Spam object at 0x107195c10>
>>> super(Spam, spam).__self_class__
<class '__main__.Spam'>
При поиске атрибутов выполняется __mro__ атрибута __mro__ атрибута __self_class__, начиная с одной позиции после позиции __thisclass__, и результаты связываются.
__self_class__ атрибута super() с одним аргументом атрибутам __self__ и __self_class__ присвоено значение None и он пока не может выполнять поиск:
>>> super(Spam)
<super: <class 'Spam'>, NULL>
>>> super(Spam).__self__ is None
True
>>> super(Spam).__self_class__ is None
True
>>> super(Spam).bar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'super' object has no attribute 'bar'
Объект поддерживает протокол дескриптора, поэтому вы можете связать его так же, как вы можете связать метод:
>>> super(Spam).__get__(spam, Spam)
<super: <class 'Spam'>, <Spam object>>
>>> super(Spam).__get__(spam, Spam).bar()
'bar on Foo'
Это означает, что вы можете хранить такой объект в классе и использовать его для перехода к родительским методам:
>>> class Eggs(Spam):
... pass
...
>>> Eggs.parent = super(Eggs)
>>> eggs = Eggs()
>>> eggs.parent
<super: <class 'Eggs'>, <Eggs object>>
>>> eggs.parent.bar()
'bar on Spam'
Основным вариантом использования было бы избежать поиска класса каждый раз, когда вы используете super():
class Foo:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
setattr(cls, f"_{cls.__name__}__sup", super(cls))
def bar(self):
return 'bar on Foo'
class Spam(Foo):
def bar(self):
return "spammed: " + self.__sup.bar()
но это ломается при использовании метода класса (так как cls.__sup wont bind) и был заменен Python 3s super() с нулевыми аргументами.