creating many similar properties

George Sakkis george.sakkis at gmail.com
Wed Oct 18 10:13:21 CEST 2006


Carl Banks wrote:
> Lee Harr wrote:
> > I understand how to create a property like this:
> >
> > class RC(object):
> >     def _set_pwm(self, v):
> >         self._pwm01 = v % 256
> >     def _get_pwm(self):
> >         return self._pwm01
> >     pwm01 = property(_get_pwm, _set_pwm)
> >
> >
> > But what if I have a whole bunch of these pwm properties?
> >
> > I made this:
> >
> > class RC(object):
> >     def _makeprop(name):
> >         prop = '_%s' % name
> >         def _set(self, v):
> >             v_new = v % 256
> >             setattr(self, prop, v_new)
> >         def _get(self):
> >             return getattr(self, prop)
> >         return property(_get, _set)
> >
> >     pwm01 = _makeprop('pwm01')
> >     pwm02 = _makeprop('pwm02')
> >
> >
> > Not too bad, except for having to repeat the name.
> >
> > I would like to just have a list of pwm names and
> > have them all set up like that. It would be nice if
> > each one was set to a default value of 127 also....
> >
> > Any thoughts?
>
>
> The metaclass solution.  I use this idiom occasionally, whenever I want
> to fiddle with the class dict before letting the type constructor at
> it.
>
> class mod256metatype(type):
>     def __new__(metatype,name,bases,clsdict):
>         for sym in clsdict.get('__mod256__',()):
>             prop = '_%s'  % sym
>             def _set(self,v):
>                 setattr(self,prop,v%256)
>             def _get(self):
>                 return getattr(self,prop)
>             clsdict[sym] = property(_get,_set)
>         return type.__new__(metatype,name,bases,clsdict)
>
> class RC(object):
>     __metaclass__ = mod256metatype
>     __mod256__ = ["pwm01","pwm02"]

There's a subtle common bug here: all _get and _set closures will refer
to the last property only. You have to remember to write "def
_set(self,v,prop=prop)" and similarly for _get to do the right thing.
By the way, I can't think of a case where the current behavior (i.e.
binding the last value only) is the desired one. Is this just an
implementation wart or am I missing something ?

George




More information about the Python-list mailing list