2015-05-12 3 views
7

Neu in Python und nachdem ich ein wenig gelesen habe, mache ich einige Methoden in meinen benutzerdefinierten Klassenmethoden anstatt Instanzmethoden.Python - warum kann ich eine Klassenmethode mit einer Instanz aufrufen?

Also testete ich meinen Code, aber ich hatte nicht einen Teil der Methode geändert ruft die Methode in der Klasse und nicht die Instanz zu nennen, aber sie arbeiteten noch:

class myclass: 
    @classmethod: 
    def foo(cls): 
     print 'Class method foo called with %s.'%(cls) 

    def bar(self): 
     print 'Instance method bar called with %s.'%(self) 

myclass.foo() 
thing = myClass() 
thing.foo() 
thing.bar() 

Dies erzeugt:

class method foo called with __main__.myclass. 
class method foo called with __main__.myclass. 
instance method bar called with <__main__.myclass instance at 0x389ba4>. 

Also was ich frage mich ist, warum ich eine Klassenmethode (foo) auf einer Instanz (thing.foo) aufrufen kann (obwohl es die Klasse ist, die an die Methode übergeben wird)? Es macht einen Sinn, da 'Sache' eine 'myClass' ist, aber ich habe erwartet, dass Python einen Fehler gibt, der etwas sagt, wie 'foo ist eine Klassenmethode und kann nicht für eine Instanz aufgerufen werden'.

Ist dies nur eine erwartete Folge der Vererbung mit dem 'Ding'-Objekt, das die foo-Methode von seiner Oberklasse erbt?

Wenn ich versuche, die Instanzmethode über die Klasse zu nennen:

myclass.bar() 

dann bekomme ich:

TypeError: unbound method bar() must be called with myclass instance... 

, die durchaus Sinn macht.

+0

In Python werden Methoden nicht * on * etwas aufgerufen. 'thing.foo' ist kein Methodenaufruf, es ist ein Attributzugriff, es ist im Grunde dasselbe wie' getattr (ding, "foo") '. – Alexey

+0

@Alexey Sicher ist 'foo' eine Methode und 'ding.foo()' ruft die 'foo' Methode des Objekts' thing' auf? Ist ein Attribut Pythons Terminologie nicht für andere Sprachen, auf die es sich als Variable oder Eigenschaft bezieht? –

+0

Ich denke, dass "' (thing.foo)() 'ruft die' foo' Methode des Objekts 'thing'" (Klammern für die Klarheit) ist eine Metapher für "(thing.foo)()' ruft die Callable-Objekt 'thing.foo'", das ist es. AFAIU, dieses Objekt wird dynamisch erzeugt, wenn 'getattr (ding," foo ")' aufgerufen wird, und natürlich hat es einen Verweis auf das 'thing' Objekt. – Alexey

Antwort

6

Sie können es für eine Instanz aufrufen, weil @classmethod ein decorator ist (es nimmt eine Funktion als Argument und gibt eine neue Funktion zurück).

Hier einige relavent Informationen aus dem Python documentation

Es kann entweder von der Klasse (wie Cf()) oder auf einer Instanz (wie C(). F()) aufgerufen werden . Die Instanz wird außer für ihre Klasse ignoriert. Wenn für eine abgeleitete Klasse eine Klassenmethode aufgerufen wird, wird das abgeleitete Klassenobjekt als implizites erstes Argument übergeben.

Es gibt auch eine ziemlich gute SO-Diskussion auf @classmethodhere.

+0

Danke - Ich habe verschiedene Suchen nach Vererbung, Klassenmethoden usw. durchgeführt, aber wie Sie sich vorstellen können, waren die Ergebnisse überwältigend. Ich wäre ziemlich glücklich gewesen, einfach zu akzeptieren, dass es funktioniert, aber als Assembler-Programmierer mag ich es zu wissen, wie die Dinge unter der Decke funktionieren. –

+0

"Sie können es für eine Instanz aufrufen, weil @classmethod ein Decorator ist" - ich folge dieser Logik nicht. – Alexey

+0

@Alexey wissen Sie, was ein Dekorateur ist? – John