Ich versuche die super () Funktion in Python zu lernen.
Ich dachte, ich hätte es verstanden, bis ich über dieses Beispiel (2.6) kam und feststeckte.
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)
>>>
Es war nicht das, was ich erwartet hatte, als ich diese Zeile direkt vor dem Beispiel las:
Wenn wir eine Klassenmethode verwenden, haben wir keine Instanz, mit der wir super aufrufen können. Zum Glück funktioniert super sogar mit einem Typ als zweitem Argument. --- Der Typ kann wie unten gezeigt direkt an super übergeben werden.
Genau das, was Python mir sagt, ist nicht möglich, wenn man sagt, dass do_something () mit einer Instanz von B aufgerufen werden soll.
Antworten:
Manchmal müssen Texte eher für den Geschmack der Idee als für die Details gelesen werden. Dies ist einer dieser Fälle.
Auf der verlinkten Seite sollten die Beispiele 2.5, 2.6 und 2.7 alle eine Methode verwenden
do_your_stuff
. (Das heißt,do_something
sollte geändert werdendo_your_stuff
.)Darüber hinaus muss, wie Ned Deily betonte ,
A.do_your_stuff
eine Klassenmethode sein.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
gibt eine gebundene Methode zurück (siehe Fußnote 2 ). Dacls
als zweites Argument an übergeben wurdesuper()
, wird escls
an die zurückgegebene Methode gebunden. Mit anderen Worten,cls
wird als erstes Argument an die Methodedo_your_stuff()
der Klasse A übergeben.Um es noch einmal zu wiederholen: Bewirkt,
super(B, cls).do_your_stuff()
dassA
diedo_your_stuff
Methode von aufgerufen wird, wobeicls
als erstes Argument übergeben wird. Damit das funktioniert, mussA
'sdo_your_stuff
eine Klassenmethode sein. Die verlinkte Seite erwähnt das nicht, aber das ist definitiv der Fall.PS.
do_something = classmethod(do_something)
ist die alte Art, eine Klassenmethode zu erstellen. Die neue (er) Möglichkeit besteht darin, den @ classmethod-Dekorator zu verwenden.Beachten Sie, dass
super(B, cls)
nicht durch ersetzt werden kannsuper(cls, cls)
. Dies könnte zu Endlosschleifen führen. Zum Beispiel,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()
wird erhöhen
RuntimeError: maximum recursion depth exceeded while calling a Python object
.Wenn
cls
istC
, dannsuper(cls, cls)
suchtC.mro()
für die Klasse , die nach kommtC
.In [161]: C.mro() Out[161]: [__main__.C, __main__.B, __main__.A, object]
Da diese Klasse
B
, wanncls
istC
,super(cls, cls).do_your_stuff()
immer aufruftB.do_your_stuff
. Dasuper(cls, cls).do_your_stuff()
innen aufgerufen wirdB.do_your_stuff
, rufen Sie am EndeB.do_your_stuff
in einer Endlosschleife auf.In Python3 wurde die 0-Argument-Form von
super
hinzugefügt, damitsuper(B, cls)
sie durch ersetzt werden kannsuper()
, und Python3 wird aus dem Kontext herausfinden, dasssuper()
in der Definition vonclass B
gleich sein solltesuper(B, cls)
.Aber unter keinen Umständen ist
super(cls, cls)
(oder aus ähnlichen Gründensuper(type(self), self)
) jemals richtig.quelle
super(cls, cls)
ist mit ziemlicher Sicherheit ein Fehler. Ich habe den obigen Beitrag bearbeitet, um zu erklären, warum.In Python 3 können Sie die Angabe von Argumenten für Folgendes überspringen
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."
quelle
RuntimeError: super(): no arguments
Ich habe den Artikel aktualisiert, um ihn etwas klarer zu gestalten: Python-Attribute und -Methoden # Super
Ihr Beispiel mit der obigen Klassenmethode zeigt, was eine Klassenmethode ist - sie übergibt die Klasse selbst anstelle der Instanz als ersten Parameter. Sie benötigen jedoch nicht einmal eine Instanz, um die Methode aufzurufen, z.
>>> class A(object): ... @classmethod ... def foo(cls): ... print cls ... >>> A.foo() # note this is called directly on the class <class '__main__.A'>
quelle
Das Beispiel von der Webseite scheint wie veröffentlicht zu funktionieren. Haben Sie auch eine
do_something
Methode für die Oberklasse erstellt, diese aber nicht zu einer Klassenmethode gemacht? So etwas gibt Ihnen diesen Fehler:>>> 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)
quelle
super
Aufrufs in der B do_something-Methode besteht darin, eine Methode dieses Namens in einer ihrer Oberklassen aufzurufen. Wenn es in A (oder in Object) keine gibt, schlägt der Aufruf von B (). Do_something () mit fehlsuper object has no attribute do_something
. ~ unutbu weist zu Recht darauf hin, dass das Beispiel im Dokument fehlerhaft ist.Ich denke, ich habe den Punkt jetzt dank dieser schönen Seite und der schönen Gemeinschaft verstanden.
Wenn es Ihnen nichts ausmacht, korrigieren Sie mich bitte, wenn ich mich in Bezug auf Klassenmethoden irre (die ich jetzt zu verstehen versuche):
# 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 >>>
Ich hoffe diese Abbildung zeigt ..
quelle