2016-02-10 4 views
6

Ich bemerkte, dass, wenn ich ein Klassenattribut gleich einer Funktion definiere, wenn ich eine Instanz dieser Klasse erstelle, das Attribut eine gebundene Methode wird. Kann mir jemand den Grund für dieses Verhalten erklären?Python - Funktion als Klassenattribut wird eine gebundene Methode

In [9]: def func(): 
    ...:  pass 
    ...: 

In [10]: class A(object): 
    ....:  f = func 
    ....:  

In [11]: a = A() 

In [12]: a.f 
Out[12]: <bound method A.func of <__main__.A object at 0x104add190>> 

In [13]: a.f() 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-13-19134f1ad9a8> in <module>() 
----> 1 a.f() 
    global a.f = <bound method A.func of <__main__.A object at 0x104add190>> 

TypeError: func() takes no arguments (1 given) 

Antwort

7

Sie haben dem Attribut f eine Funktion zugewiesen. Da die Funktion jetzt innerhalb einer Klasse liegt, wird sie zu einer Methode, insbesondere zu einer gebundenen Methode (weil sie an das Objekt gebunden ist, further explanation here).

Methoden in Klassen erhalten zumindest einen Parameter (self), es sei denn, es ausdrücklich nicht gesagt wird - siehe class methods and static methods - aus diesem Grund der Fehler sagt, dass func keine Argumente hat (wie es als def func(): definiert ist), sondern erhielt 1 (self)

zu tun, was Sie wollen, sollten Sie python sagen, dass Sie eine static method

def func(): 
    pass 

class A(object): 
    f = staticmethod(func) 
verwenden
1

Python ist nicht eine Nachricht basierend OO System . Stattdessen werden Eigenschaften ähnlich wie in JavaScript in First-Class-Funktionen aufgelöst und dann aufgerufen. Das Verhalten unterscheidet sich ein wenig in der Mechanik, wie entdeckt.

In Python ist das Erfordernis, dass Verfahren zumindest einen Parameter haben, normalerweise self genannt, die geliefert werden automatisch die zugeordnete Instanz wenn es als eine Methode aufgerufen wird.

Darüber hinaus (und vielleicht zu dem Punkt der Frage) unterscheidet Python nicht zwischen der Verwendung von def f.. oder f = some_func() beim Erstellen von Instanzelementbindungen; Wohl passt das Verhalten außerhalb von Klassen.

In dem Beispiel wird durch die Zuweisung der Funktion an die Instanz erwartet, dass sie wie eine Instanzmethode behandelt wird. Es ist die exakt gleiche - parameterlose - Funktion in beiden Fällen genannt; nur die zukünftige Verwendung von solchen ist relevant.

Jetzt, im Gegensatz zu JavaScript, behandelt Python Methoden und Objektverknüpfungen durch das Konzept der gebundenen Methoden - Funktionen, die als Methoden aufgelöst werden, sind immer 'gebunden'.

Das Verhalten von a.f, das eine gebundene Methode zurückgibt - Funktion, die das gebundene Objekt automatisch an den ersten Parameter als self liefert - erfolgt unabhängig von der Quelle der Funktion. In diesem Fall bedeutet dies, dass die parameterlose Funktion nicht verwendet werden kann, wenn sie "gebunden" ist, da sie keinen Parameter self akzeptiert.

Als Demonstration wird im Folgenden auf die gleiche Art und Weise fehlschlagen, da die Quelle zugrunde liegende Methode macht nicht die Mindestanforderungen an die Annahme der Instanz als Argument erfüllen:

g = a.f 
g() 

In diesem Fall ruft g() ist entspricht dem Aufruf func(a).


Zum Vergleich, Java, C#, Ruby und SmallTalk sind Nachricht basierte OO-Systeme - in dieser Aufgabe gesagt wird ein Verfahren durch einen ‚Namen‘ aufzurufen, anstatt ein Verfahren zum Auflösen (oder Funktion) als Wert, der aufgerufen werden kann.

Verwandte Themen