Idee: Ersetze Eigenschaftendeskriptor, um die Einstellung bestimmter Objekte zu ermöglichen. Wenn ein Wert nicht explizit auf diese Weise festgelegt wird, wird der ursprüngliche Eigenschaftengetter aufgerufen.
Das Problem besteht darin, wie die explizit festgelegten Werte gespeichert werden. Wir können keinen dict
Schlüssel verwenden, der durch gepatchte Objekte getastet wird, da 1) sie nicht notwendigerweise durch Identität vergleichbar sind; 2) Dies verhindert, dass gepatchte Objekte von Müll gesammelt werden. Für 1) könnten wir eine Handle
schreiben, die Objekte umschließt und die Vergleichssemantik durch Identität überschreibt und für 2) könnten wir verwenden. Allerdings konnte ich diese beiden nicht zusammen arbeiten lassen.
Daher verwenden wir einen anderen Ansatz zum Speichern der explizit gesetzten Werte auf dem Objekt selbst, mit einem "sehr unwahrscheinlich Attributnamen". Es ist natürlich immer noch möglich, dass dieser Name mit etwas kollidiert, aber das ist in Sprachen wie Python ziemlich inhärent.
Dies funktioniert nicht bei Objekten, die keinen -Steckplatz haben. Ein ähnliches Problem würde sich jedoch für schwache Referenzen ergeben.
class Foo:
@property
def bar (self):
return 'original'
class Handle:
def __init__(self, obj):
self._obj = obj
def __eq__(self, other):
return self._obj is other._obj
def __hash__(self):
return id (self._obj)
_monkey_patch_index = 0
_not_set = object()
def monkey_patch (prop):
global _monkey_patch_index, _not_set
special_attr = '$_prop_monkey_patch_{}'.format (_monkey_patch_index)
_monkey_patch_index += 1
def getter (self):
value = getattr (self, special_attr, _not_set)
return prop.fget (self) if value is _not_set else value
def setter (self, value):
setattr (self, special_attr, value)
return property (getter, setter)
Foo.bar = monkey_patch (Foo.bar)
f = Foo()
print (Foo.bar.fset)
print(f.bar) # baz
f.bar = 42 # MAGIC!
print(f.bar) # 42
Haben Sie bedeuten, dass Sie 'f.bar' kein Eigentum mehr (und wenn ja, ohne Auswirkungen auf andere Instanzen?) Machen wollen, beachten, dass Eigenschaften, wie andere Deskriptoren gespeichert sind von der Klasse * * . – jonrsharpe
Ja, ich möchte den Wert beeinflussen, der beim Zugriff auf 'f.bar' nur in dieser Instanz zurückgegeben wird. – deceze
Ich denke, der einzige Weg, dies zu tun wäre, 'f .__ dict__' direkt zu ändern, indem man ein neues' bar'-Attribut bereitstellt, das vor der Eigenschaft nachgeschlagen wird, aber nur für diese einzelne Instanz. – jonrsharpe