Er, instead of "getattr(self,...) you gotta do "object.__getattr__(self,...)" and same for setattr and delattr. Dumb error on my part. (Otherwise you get infinite recursion!)
On Feb 6, 2008 12:43 PM, Jared Grubb <[EMAIL PROTECTED]> wrote: > Here's one way of doing what you're asking... I would suggest using > __getattribute__ and __setattr__ to dispatch the methods to the custom class > you invent that holds all those properties. > > For example (I simplified your makeprops into __init__ just to keep the > example short, but you can probably see the idea here..) > > class A(object): > def __init__(self, **kw): > class _PropHolder(object): > pass > for k,v in kw.items(): > setattr(_PropHolder, k, property(fget=itemgetter(k))) > self._custom_props = _PropHolder() > def __getattribute__(self, attr): > try: > return getattr(self._custom_props, attr) > except AttributeError: > return getattr(self, attr) > def __setattr__(self, attr, val): > if hasattr(self._custom_props, attr): > setattr(self._custom_props, attr, val) > else: > setattr(self, attr, val) > def __delattr__(self, attr): > if hasattr(self._custom_props, attr): > delattr(self._custom_props, attr) > else: > delattr(self, attr) > > > > > On 6 Feb 2008, at 12:06, [EMAIL PROTECTED] wrote: > > Hi all, > > So I understand that properties belong to a class not an instance, but > nonetheless I want to add properties to an instance. I have a class > which when an instance is created runs some fairly complicated code > and produces a set of names which I'd like to be able to access via > properties. At the moment, I'm using something like obj.getvar(name) > but I'd like to be able to write obj.name. (Note that they can't be > just standard attributes because they only get computed when they are > accessed.) I could generate functions like obj.name() but I want it to > be obj.name instead. > > The solution I've come up with is to create a new class for each > object which is just the real class with some extra properties, and > then dynamically change the class of the object to this new class. > This seems to work, but I wonder if (a) there is a nicer solution than > the one I'll post below, (b) if there are any dangers or pitfalls of > this approach. The obvious difficulty is with derived classes. At the > moment, I'm insisting that a derived class has to call a makeprops() > method to create the properties. > > It's kind of similar to this recipe: > > http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/197965 > > but that recipe has a much simpler situation in which the properties > and values are known at the time of the creation of the object (by > contrast, I don't know what the properties are until the end of the > __init__ method). > > Any thoughts? > > Code below to illustrate my approach. > > import warnings > from operator import itemgetter > > class A(object): > def __init__(self,**kwds): > self._kwds = kwds > self.makeprops() > def __getitem__(self,i): > return self._kwds[i] > def makeprops(self): > if not hasattr(self,'_madeprops'): > self._madeprops = set() > self._failedprops = set() > class _A(self.__class__): > pass > for k,v in self._kwds.items(): > if not k in self._madeprops and k in dir(self): > if not k in self._failedprops: > warnings.warn("Cannot create property "+k+", > already used in object "+str(self),RuntimeWarning) > self._failedprops.add(k) > else: > setattr(_A,k,property(fget=itemgetter(k))) > self._madeprops.add(k) > self.__class__ = _A > > class B(A): > def __init__(self,**kwds): > super(B,self).__init__(**kwds) > self.makeprops() > > class C(A): > def __init__(self,**kwds): > self._kwds = kwds > > a = A(x=1) > b = B(x=2,makeprops=3) > c = C(x=3) > print isinstance(a,A), isinstance(a,B), isinstance(a,C) # True False > False > print isinstance(b,A), isinstance(b,B), isinstance(b,C) # True True > False > print isinstance(c,A), isinstance(c,B), isinstance(c,C) # True False > True > print a.__class__ # <class '__main__._A'> > print b.__class__ # <class '__main__._A'> > print c.__class__ # <class '__main__.C'> > print a.x # 1 > print b.x # 2 > print b.makeprops # <bound method _A.makeprops of <__main__._A object > at 0x00A86810>> > try: > print c.x # raises exception > except AttributeError: > print "c has no element x" > c.makeprops() > print c.x # 3 > print a.__class__ # <class '__main__._A'> > print b.__class__ # <class '__main__._A'> > print c.__class__ # <class '__main__._A'> > > --- > Dan Goodman > http://thesamovar.net/contact > -- > http://mail.python.org/mailman/listinfo/python-list > > >
-- http://mail.python.org/mailman/listinfo/python-list