Adding properties to objects

Peter Otten __peter__ at web.de
Tue Apr 13 14:37:37 EDT 2004


Matthew Barnes wrote:

> Is it possible to add properties to objects dynamically?
> 
> I have an instance (x) of some new-style class (Foo), and I would like
> to be able to do something like:
> 
>>>> x = Foo()
>>>> x.myproperty = property(getsomething, setsomething, delsomething);
>>>> x.myproperty        # invokes getsomething
>>>> x.myproperty = 1    # invokes setsomething
>>>> del x.myproperty    # invokes delsomething
> 
> However, when I evaluate x.myproperty I get back a property object
> (which makes sense).  I get the feeling I'm missing a step to "bind"
> the property object to the class instance.
> 
> Is this possible (it's Python... of course it's possible, right?), and
> if so, how?

Fresh from the mad coders' department, here's how to dynamically change an
object's class to get the desired effect:

import new
class Foo(object):
    def __setattr__(self, name, value):
        if isinstance(value, property):
            klass = new.classobj(self.__class__.__name__, (self.__class__,),
{})
            setattr(klass, name, value)
            self.__class__ = klass
        else:
            object.__setattr__(self, name, value)


f1 = Foo()
f1.name = "first"

def set1(self, v):
    self.name = v[1:-1]
def get1(self):
    return "(%s)" % self.name
f1.prp = property(get1, set1)

f2 = Foo()
f2.name = "second"

def set2(self, v):
    self.name = v[2:-2]
def get2(self):
    return "<<%s>>" % self.name
f2.prp = property(get2, set2)

print f1.prp, f2.prp
f2.prp = "((was second))"
print f1.prp, f2.prp
f2.__class__.prp = f1.__class__.prp
print f1.prp, f2.prp


If you try the above approach, you will of course end up with more classes
than instances - if you only expect a limited number of dynamic properties
you could put all combinations into a class cache.

:-)

Peter




More information about the Python-list mailing list