Warum schlägt setattr auf einer gebundenen Methode

Im folgenden folgt setattr in der ersten setattr , scheitert aber im zweiten mit:

 AttributeError: 'method' object has no attribute 'i' 

Warum ist das und gibt es eine Möglichkeit, ein Attribut auf eine Methode zu setzen, so dass es nur auf einer Instanz existiert, nicht für jede Instanz der Klasse?

 class c: def m(self): print(type(cm)) setattr(cm, 'i', 0) print(type(self.m)) setattr(self.m, 'i', 0) 

Python 3.2.2

2 Solutions collect form web for “Warum schlägt setattr auf einer gebundenen Methode”

Die kurze Antwort: Es gibt keine Möglichkeit, benutzerdefinierte Attribute zu gebundenen Methoden hinzuzufügen.

Die lange Antwort folgt.

In Python gibt es Funktionsobjekte und Methodenobjekte . Wenn Sie eine Klasse definieren, erstellt die def Anweisung ein Funktionsobjekt , das innerhalb der Klasse 'namespace lebt:

 >>> class c: ... def m(self): ... pass ... >>> cm <function m at 0x025FAE88> 

Funktionsobjekte haben ein spezielles __dict__ Attribut, das benutzerdefinierte Attribute enthalten kann:

 >>> cmi = 0 >>> cm__dict__ {'i': 0} 

Methodenobjekte sind verschiedene Tiere. Sie sind winzige Objekte, die nur einen Hinweis auf das entsprechende Funktionsobjekt ( __func__ ) und einen zu seinem __self__ ( __self__ ) halten:

 >>> c().m <bound method cm of <__main__.c object at 0x025206D0>> >>> c().m.__self__ <__main__.c object at 0x02625070> >>> c().m.__func__ <function m at 0x025FAE88> >>> c().m.__func__ is cm True 

Methodenobjekte bieten ein spezielles __getattr__ , das den Attributzugriff auf das Funktionsobjekt leitet:

 >>> c().mi 0 

Dies gilt auch für die Eigenschaft __dict__ :

 >>> c().m.__dict__['a'] = 42 >>> cma 42 >>> c().m.__dict__ is cm__dict__ True 

Die Einstellung von Attributen folgt den Standardregeln, und da sie nicht über ihr eigenes __dict__ , gibt es keine Möglichkeit, beliebige Attribute zu setzen.

Dies ist ähnlich wie benutzerdefinierte Klassen, die __slots__ definieren und kein __dict__ Steckplatz, wenn versucht wird, einen nicht vorhandenen Slot zu setzen, erhöht ein AttributeError (siehe die docs auf __slots__ für weitere Informationen):

 >>> class c: ... __slots__ = ('a', 'b') ... >>> x = c() >>> xa = 1 >>> xb = 2 >>> xc = 3 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'c' object has no attribute 'c' 

Q: "Gibt es eine Möglichkeit, ein Attribut auf eine Methode zu setzen, so dass es nur auf einer Instanz existiert, nicht für jede Instanz der Klasse?"

A: Ja:

 class c: def m(self): print(type(cm)) setattr(cm, 'i', 0) print(type(self)) setattr(self, 'i', 0) 

Die statische Variable auf Funktionen in der Post, die Sie verknüpfen, ist für Methoden nicht sinnvoll. Es setzt ein Attribut auf die Funktion, so dass dieses Attribut zur Verfügung steht das nächste Mal die Funktion aufgerufen wird, so können Sie einen Zähler oder was nicht machen.

Aber Methoden haben eine Objektinstanz mit ihnen verbunden (Selbst). Daher musst du keine Attribute auf die Methode setzen, da man sie einfach auf die Instanz setzen kann. Das ist genau das, was die Instanz ist.

Die Post, die Sie verknüpfen, zeigt, wie man eine Funktion mit einer statischen Variablen macht. Ich würde sagen, dass in Python so wäre es falsch. Stattdessen schau dir diese Antwort an: Was ist das Python-Äquivalent von statischen Variablen innerhalb einer Funktion?

Das ist der Weg, um es in Python in einer Weise zu tun, die klar und leicht verständlich ist. Sie verwenden eine Klasse und machen sie kündbar. Das Festlegen von Attributen auf Funktionen ist möglich und es gibt wahrscheinlich Fälle, wo es eine gute Idee ist, aber im Allgemeinen wird es am Ende verwirrend Menschen.

Python ist die beste Programmiersprache der Welt.