Я пытаюсь изучить функцию super () в Python.
Я думал, что понял это, пока не наткнулся на этот пример (2.6) и не застрял.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "test.py", line 9, in do_something
do_something = classmethod(do_something)
TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)
>>>
Это было не то, что я ожидал, когда прочитал эту строку прямо перед примером:
Если мы используем метод класса, у нас нет экземпляра для вызова super. К счастью для нас, super работает даже с типом в качестве второго аргумента. --- Тип можно передать непосредственно в super, как показано ниже.
Это именно то, что говорит мне Python, невозможно, говоря, что do_something () должен вызываться с экземпляром B.
Ответы:
Иногда тексты нужно читать больше из-за изюминки идеи, а не из-за деталей. Это один из таких случаев.
В связанной странице , примеры 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
«sdo_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(B, cls).do_your_stuff() # CORRECT super(cls, cls).do_your_stuff() # WRONG class C(B): @classmethod def do_your_stuff(cls): print('This is C') # super(C, cls).do_your_stuff() # CORRECT super(cls, cls).do_your_stuff() # WRONG 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)
) никогда не является правильным.источник
super(cls, cls)
это почти наверняка ошибка. Я отредактировал сообщение выше, чтобы объяснить, почему.В Python 3 вы можете не указывать аргументы для
super
,class A: @classmethod def f(cls): return "A's f was called." class B(A): @classmethod def f(cls): return super().f() assert B.f() == "A's f was called."
источник
RuntimeError: super(): no arguments
Я обновил статью, чтобы сделать ее немного понятнее: Атрибуты и методы Python # Super
В приведенном выше примере с использованием метода класса показано, что такое метод класса - он передает сам класс вместо экземпляра в качестве первого параметра. Но вам даже не нужен экземпляр для вызова метода, например:
>>> class A(object): ... @classmethod ... def foo(cls): ... print cls ... >>> A.foo() # note this is called directly on the class <class '__main__.A'>
источник
Пример с веб-страницы, похоже, работает как опубликованный. Вы также создали
do_something
метод для суперкласса, но не превратили его в метод класса? Что-то вроде этого даст вам эту ошибку:>>> class A(object): ... def do_something(cls): ... print cls ... # do_something = classmethod(do_something) ... >>> class B(A): ... def do_something(cls): ... super(B, cls).do_something() ... do_something = classmethod(do_something) ... >>> B().do_something() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in do_something TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)
источник
super
вызова метода B do_something состоит в том, чтобы вызвать метод с таким именем в одном из его суперклассов. Если его нет в A (или в Object), вызов B (). Do_something () завершается ошибкойsuper object has no attribute do_something
. ~ unutbu правильно указывает, что пример в документе ошибочен.Думаю, теперь я понял суть дела благодаря этому красивому сайту и прекрасному сообществу.
Если вы не возражаете, поправьте меня, если я ошибаюсь в методах классов (которые я сейчас пытаюсь полностью понять):
# EXAMPLE #1 >>> class A(object): ... def foo(cls): ... print cls ... foo = classmethod(foo) ... >>> a = A() >>> a.foo() # THIS IS THE CLASS ITSELF (__class__) class '__main__.A' # EXAMPLE #2 # SAME AS ABOVE (With new @decorator) >>> class A(object): ... @classmethod ... def foo(cls): ... print cls ... >>> a = A() >>> a.foo() class '__main__.A' # EXAMPLE #3 >>> class B(object): ... def foo(self): ... print self ... >>> b = B() >>> b.foo() # THIS IS THE INSTANCE WITH ADDRESS (self) __main__.B object at 0xb747a8ec >>>
Я надеюсь, что эта иллюстрация показывает ..
источник