2009-11-29 15 views
43

Ich versuche, die Funktion super() in Python zu lernen.Verwenden Super mit einer Klassenmethode

Ich hatte zwar einen Griff davon, bis ich über dieses Beispiel (2.6) kam und feststeckte.

http://www.cafepy.com/article/python_attributes_and_methods/python_attributes_and_methods.html#super-with-classmethod-example

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, wenn ich diese Zeile lesen direkt vor dem Beispiel:

If we're using a class method, we don't have an instance to call super with. Fortunately for us, super works even with a type as the second argument. --- The type can be passed directly to super as shown below.

das ist genau das, was Python mir sagt, ist nicht möglich, dass do_something sagen() sollte mit einer Instanz von B aufgerufen werden.

Vielen Dank im Voraus

+0

Mögliche Duplikat [Aufruf einer Basisklasse classmethod in Python] (https://stackoverflow.com/questions/1269217/calling-a-base-classs-classmethod-in-python) –

Antwort

55

Manchmal müssen Texte eher für den Geschmack der Idee gelesen werden als für die Details. Dies ist einer dieser Fälle.

In der linked page sollten die Beispiele 2.5, 2.6 und 2.7 alle eine Methode verwenden, do_your_stuff. (Das heißt, sollte do_something-do_your_stuff geändert werden.)

Zusätzlich als Ned Deily pointed out, A.do_your_stuff eine Klassenmethode sein muss.

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 liefert eine gebunden Methode (siehe footnote 2). Da cls als zweites Argument an super() übergeben wurde, wird es cls, die an die zurückgegebene Methode gebunden wird. Mit anderen Worten, cls wird als erstes Argument an die Methode do_you_stuff() übergeben.

So super(B, cls).do_your_stuff() verursacht A ‚s do_your_stuff Methode mit cls als erstes Argument übergeben genannt werden. Damit das funktioniert, muss A do_your_stuff eine Klassenmethode sein. Die verlinkte Seite erwähnt das nicht, aber es ist wahr.

PS. do_something = classmethod(do_something) ist die alte Art, eine Klassenmethode zu erstellen. Der neue (er) Weg ist die Verwendung des @ classmethod Dekorators.

2

Das Beispiel von der Webseite scheint wie veröffentlicht zu funktionieren. Hast du eine do_something Methode auch für die Oberklasse erstellt, aber nicht in eine Klassenmethode? So etwas wird Ihnen diesen Fehler geben:

+0

Nein, meine A-Klasse sieht so aus: Klasse A (Objekt): def do_your_stuff (self): print "das ist A" Ist es notwendig, "Klasse A" zu haben, wie Sie es gepostet haben? (mit do_something = classmethod (do_something))? Ich fühle mich wie das Dokument nichts darüber erzählt .. – dezza

+1

Der ganze Punkt des "Super" Aufrufs in der B do_something Methode ist eine Methode dieses Namens in einer seiner Oberklassen aufzurufen. Wenn es in A (oder in Object) keinen gibt, schlägt der B(). Do_something() -Aufruf mit "Super-Objekt hat kein Attribut do_something" fehl. ~ unutbu weist zu Recht darauf hin, dass das Beispiel im Dokument fehlerhaft ist. –

0

Ich denke, ich habe den Punkt jetzt dank dieser schönen Website und schöne Gemeinschaft verstanden.

Wenn Sie nichts dagegen mich nicht bitte korrigieren, wenn ich auf Class falsch bin (was ich jetzt zu verstehen, voll bin versucht):


# 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 ..

+0

Für eine Erklärung der Klassenmethoden, vielleicht finden Sie das hilfreich: http://stackoverflow.com/questions/1669445/what-is-the-difference-between-a-static-method-and-class-method-in -python/1669524 # 1669524 – unutbu

2

Ich habe den Artikel aktualisiert, um es klarer etwas zu machen: Python Attributes and Methods # Super

Ihr Beispiel oben mit Class zeigt, was eine Klassenmethode ist - es geht die Klasse selbst, anstatt die Instanz als ersten Parameter. Aber Sie brauchen nicht einmal eine Instanz die Methode aufzurufen, für zB:

>>> class A(object): 
...  @classmethod 
...  def foo(cls): 
...   print cls 
... 
>>> A.foo() # note this is called directly on the class 
<class '__main__.A'> 
1

In Python 3 können Sie die Angabe Argumente für super überspringen,

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." 
+0

Diese Antwort könnte zu einer anderen Frage verschoben werden, wenn diese spezielle Frage speziell mit Python 2 zu tun hat (es ist schwer zu sagen, da die verlinkte Website, CafePy, nicht mehr verfügbar ist). – Tankobot

Verwandte Themen