Setzen von eigenen Attributen

10/05/2010 - 16:55 von Ole Streicher | Report spam
Hallo Gruppe,

basierend auf meiner letzten (unbeantworteten) Frage hier die
Fortsetzung:

Ich möchte gerne an einer Klasse selbst dynamisch Properties definieren,
d.h., ich habe eine Liste von Attributnamen und eine zugehörige set- und
get-Funktion:

other.set("attr1", value1)

resp.

other.get("attr1")

Die Liste der so setzbaren Objekte erhalte ich mit other.getAttr().

Die hàtte ich jetzt gerne als "property" eingebunden, d.h. sobald bei
einem Objekt "my" der Klasse

class Myobj(object):
def __init__(self, other):
self.other = other

das das Attribute "attr1" aufrufe, soll das an other delegiert werden:

my = MyObj()
my.attr1 = 5 # --> my.other.set("attr1", 5)
print my.attr1 # --> print my.other.get("attr1")

Dabei möchte ich gerne die "Tab"-Completition von ipython beibehalten
(d.h. die Liste der Objekte muss vollstàndig sein), und das Objekt
"other" kann die Liste seiner Attribute durchaus àndern (d.h. nach
"other.reload()" ist es möglich, dass Attribute verschwunden sind und
neue auftauchen; das soll natürlich auch auf "my" zutreffen).

Wie mache ich das am Besten?

Viele Grüße

Ole
 

Lesen sie die antworten

#1 Thomas Rachel
11/05/2010 - 00:03 | Warnen spam
Am 10.05.2010 16:55, schrieb Ole Streicher:


Dabei möchte ich gerne die "Tab"-Completition von ipython beibehalten
(d.h. die Liste der Objekte muss vollstàndig sein), und das Objekt
"other" kann die Liste seiner Attribute durchaus àndern (d.h. nach
"other.reload()" ist es möglich, dass Attribute verschwunden sind und
neue auftauchen; das soll natürlich auch auf "my" zutreffen).

Wie mache ich das am Besten?



Vermutlich gar nicht (so ohne weiteres). Die Tab-Completion gibt nur
Elemente von __dict__ zurück sowie die über die Klasse erreichbaren
Attribute. Über __setattr__ selbst definierte funktionieren nicht.

Du könntest es entweder so machen, daß jede Instanz quasi ihre eigene
Klasse besitzt, die dann live modifiziert wird (Stichwort properties),
oder aber Deine __setattr__ könnte live __dict__ veràndert (was dann von
__getattr ignoriert werden sollte). Beides ist nicht so arg schön, aber
tendenziell würde ich zu der ersten Variante raten. Das könnte etwa so
geschehen:

class Foo(object):
def __new__(cls, **kw):
class subcls(cls):
pass
# Subclass for having own properties...
return object.__new__(subcls)
def __init__(self, **kw):
self.__dict__['_proxy'] = {}
for i in kw:
setattr(self, i, kw[i])
def __setattr__(self, k, v):
if k not in self._proxy:
# new property... k is for all of them
def getter(self):
return self._proxy[k]
def setter(self, v):
self._proxy[k] = v # new value
def deller(self):
del self._proxy[k]
delattr(self.__class__, k)
prop = property(getter, setter, deller)
setattr(self.__class__, k, prop)
# new property is set
# work around this __setattr__ (call parent's)
super(Foo, self).__setattr__(k, v)

if __name__=='__main__':
a=Foo()
b=Foo()
a.null = 0
a.eins = 1
print "D", a.__dict__
print "P", a.proxy
a.eins = 1.1
print "D", a.__dict__
print "P", a.proxy
print "E", a.eins
a.eins = 2
print "P", a.proxy
print "P", b.proxy


Ist ziemlich wüst, tut aber, was es soll.

Es gibt sicherlich noch einige andere Möglichkeiten, aber die dürften
fast ebenso wüst sein...


Thomas

Ähnliche fragen