Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Dynamic property names on class

12 views
Skip to first unread message

Bryan

unread,
Nov 13, 2009, 11:59:54 AM11/13/09
to
I have several properties on a class that have very similar behavior.
If one of the properties is set, all the other properties need to be
set to None. So I wanted to create these properties in a loop like:

class Test(object):
for prop in ['foo', 'bar', 'spam']:
# Attribute that data is actually stored in
field = '_' + prop
# Create getter/setter
def _get(self):
return getattr(self, field)
def _set(self, val):
setattr(self, field, val)
for otherProp in prop:
if otherProp != prop: setattr(self, '_' + otherProp, None)
# Assign property to class
setattr(Test, prop, property(_get, _set))

t = Test()
t.foo = 1
assert t.bar == t.spam == None

But the class Test is not defined yet, so I can't set a property on
it. How can I do this?

Diez B. Roggisch

unread,
Nov 13, 2009, 12:34:58 PM11/13/09
to
Bryan schrieb:

With a metaclass, or a post-class-creation function. Which is a
metaclass without being fancy.

Just put your above code into a function with the class in question as
argument, and invoke it after Test is defined.

Diez

Bryan

unread,
Nov 13, 2009, 1:20:32 PM11/13/09
to

I think there are some closure issues with this as I am getting very
strange results. I think all properties have the getter/setters of
whatever the last item in the list was.
t.foo = 'settingFoo' actually sets t.spam, as 'spam' was the last
property generated.

Diez B. Roggisch

unread,
Nov 13, 2009, 2:46:54 PM11/13/09
to
Bryan schrieb:

That's a FAQ. Closures capture the *names*, not the values. There are
various options to remedy this, e.g. by something like this:


def gen_property(prop):

def _get(...) # your code


return property(_get, _set)

setattr(Test, prop, gen_property(prop))


Diez

0 new messages