Próbuję nauczyć się funkcji super () w Pythonie.
Myślałem, że to rozumiem, dopóki nie doszedłem do tego przykładu (2.6) i utknąłem.
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)
>>>
Nie tego się spodziewałem, czytając ten wiersz tuż przed przykładem:
Jeśli używamy metody klasowej, nie mamy instancji, z którą można by wywołać super. Na szczęście dla nas super działa nawet z typem jako drugim argumentem. --- Typ można przekazać bezpośrednio do super, jak pokazano poniżej.
Dokładnie to, co mówi mi Python, nie jest możliwe, mówiąc, że do_something () powinno zostać wywołane z instancją B.
Odpowiedzi:
Czasami teksty trzeba czytać bardziej ze względu na smak pomysłu niż szczegóły. To jest jeden z tych przypadków.
Na stronie , do której prowadzi łącze, w przykładach 2.5, 2.6 i 2.7 należy używać jednej metody, czyli
do_your_stuff
. (Oznacza to, żedo_something
należy zmienić nado_your_stuff
.)Ponadto, jak zauważył Ned Deily ,
A.do_your_stuff
musi to być metoda klasowa.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
zwraca powiązaną metodę (patrz przypis 2 ). Ponieważcls
został przekazany jako drugi argument dosuper()
, jestcls
on powiązany z zwróconą metodą. Innymi słowy,cls
zostaje przekazany jako pierwszy argument do metodydo_your_stuff()
klasy A.Powtórzmy:
super(B, cls).do_your_stuff()
przyczynyA
„sdo_your_stuff
metodę można nazwać zcls
przekazywany jako pierwszy argument. Aby to do pracy,A
„sdo_your_stuff
musi być metoda klasy. Strona, do której prowadzi link, o tym nie wspomina, ale ostatecznie tak jest.PS.
do_something = classmethod(do_something)
jest starym sposobem tworzenia metody klasowej. Nowym (nowym) sposobem jest użycie dekoratora @classmethod.Pamiętaj, że
super(B, cls)
nie można tego zastąpićsuper(cls, cls)
. Może to prowadzić do nieskończonych pętli. Na przykład,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()
wzrośnie
RuntimeError: maximum recursion depth exceeded while calling a Python object
.Jeśli
cls
takC
,super(cls, cls)
wyszukuje następnąC.mro()
klasęC
.In [161]: C.mro() Out[161]: [__main__.C, __main__.B, __main__.A, object]
Ponieważ ta klasa jest
B
, kiedycls
jestC
,super(cls, cls).do_your_stuff()
zawsze dzwoniB.do_your_stuff
. Ponieważsuper(cls, cls).do_your_stuff()
jest wywoływany wewnątrzB.do_your_stuff
, w końcu wywołujeszB.do_your_stuff
w nieskończonej pętli.W Pythonie3 została dodana 0-argumentowa forma argumentu,
super
więcsuper(B, cls)
można ją zastąpićsuper()
, a Python3 wykryje z kontekstu, którysuper()
w definicjiclass B
powinien być równoważnysuper(B, cls)
.Ale w żadnym wypadku nie jest
super(cls, cls)
(ani z podobnych powodówsuper(type(self), self)
) nigdy nie jest poprawne.źródło
super(cls, cls)
to prawie na pewno błąd. Zredagowałem powyższy post, aby wyjaśnić, dlaczego.W Pythonie 3 możesz pominąć określanie argumentów dla
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."
źródło
RuntimeError: super(): no arguments
Zaktualizowałem artykuł, aby był nieco jaśniejszy: Atrybuty i metody Pythona # Super
Twój przykład wykorzystujący metodę classmethod powyżej pokazuje, czym jest metoda klasy - przekazuje klasę zamiast instancji jako pierwszy parametr. Ale nie potrzebujesz nawet instancji, aby wywołać metodę, na przykład:
>>> class A(object): ... @classmethod ... def foo(cls): ... print cls ... >>> A.foo() # note this is called directly on the class <class '__main__.A'>
źródło
Przykład ze strony internetowej wydaje się działać tak, jak został opublikowany. Czy stworzyłeś również
do_something
metodę dla nadklasy, ale nie uczyniłeś z niej metody klasowej? Coś takiego da ci ten błąd:>>> 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)
źródło
super
wywołania metody B do_something jest wywołanie metody o tej nazwie w jednej z jej nadklas. Jeśli nie ma takiego w A (lub Object), wywołanie B (). Do_something () kończy się niepowodzeniemsuper object has no attribute do_something
. ~ unutbu słusznie wskazuje, że przykład w dokumencie jest błędny.Myślę, że teraz zrozumiałem, o co chodzi, dzięki tej pięknej witrynie i wspaniałej społeczności.
Jeśli nie masz nic przeciwko, popraw mnie, jeśli się mylę w metodach klasowych (które teraz próbuję w pełni zrozumieć):
# 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 >>>
Mam nadzieję, że ta ilustracja pokazuje ...
źródło