Dynamisches Hinzufügen von @property in Python

Ich weiß, dass ich eine Instanzmethode dynamisch zu einem Objekt hinzufügen kann, indem ich so etwas mag:

import types def my_method(self): # logic of method # ... # instance is some instance of some class instance.my_method = types.MethodType(my_method, instance) 

Später kann ich instance.my_method() anrufen und selbst wird richtig gebunden und alles funktioniert.

Nun, meine Frage: Wie mache ich genau das Gleiche, um das Verhalten zu erhalten, das die neue Methode mit @ property verziert?

Ich würde so etwas wie raten:

 instance.my_method = types.MethodType(my_method, instance) instance.my_method = property(instance.my_method) 

Aber das tut diese instance.my_method gibt ein Eigenschaftsobjekt zurück.

2 Solutions collect form web for “Dynamisches Hinzufügen von @property in Python”

Die property Deskriptor-Objekte müssen in der Klasse leben , nicht in der Instanz , um die Wirkung zu haben, die Sie wünschen. Wenn du die vorhandene Klasse nicht ändern willst, um das Verhalten anderer Instanzen nicht zu verändern, musst du eine "Instanzklasse" machen, zB:

 def addprop(inst, name, method): cls = type(inst) if not cls.hasattr('__perinstance'): cls = type(cls.__name__, (cls,), {}) cls.__perinstance = True setattr(cls, name, property(method)) 

Ich markiere diese speziellen "per-Instanz" -Klassen mit einem Attribut, um unnötig zu vermeiden, mehrere, wenn Sie mehrere addprop Anrufe auf der gleichen Instanz machen.

Beachten Sie, dass, wie für andere Verwendungen von property , Sie die Klasse im Spiel zu neu-Stil (in der Regel durch das Erben direkt oder indirekt aus object ), nicht die alten Legacy-Stil (in Python 3 fallen gelassen), die standardmäßig zu einem zugeordnet ist Klasse ohne Basen.

Da es sich bei dieser Frage nicht darum geht, nur eine spesific-Instanz hinzuzufügen, kann die folgende Methode verwendet werden, um der Klasse eine Eigenschaft hinzuzufügen, die Eigenschaften werden allen Instanzen der Klasse YMMV ausgesetzt.

 cls = type(my_instance) cls.my_prop = property(lambda self: "hello world") print(my_instance.my_prop) # >>> hello world 

Anmerkung: Hinzufügen einer anderen Antwort, weil ich denke, @Alex Martelli, während richtig, erreicht das gewünschte Ergebnis durch Hinzufügen einer Wrapper-Methode, Meine Antwort ist beabsichtigt, direkter / einfacher zu sein, ohne zu abstrahieren, was in seine eigene Methode geht.

Python ist die beste Programmiersprache der Welt.