creating many similar properties

George Sakkis george.sakkis at gmail.com
Wed Oct 18 03:56:21 EDT 2006


Michele Simionato 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?
> >
>
> Yes, what about this?
>
> import sys
>
> def defprop(name, default=127):
>     loc = sys._getframe(1).f_locals
>     prop = '_%s' % name
>     def _set(self, v):
>         v_new = v % 256
>         setattr(self, prop, v_new)
>     def _get(self):
>         return getattr(self, prop, default)
>     loc[name] = property(_get, _set)
>
> class RC(object):
>     defprop('pwm01')
>     defprop('pwm02')
>
> rc = RC()
>
> print rc.pwm01 # 127
> print rc.pwm02 # 127
> rc.pwm02 = 1312
> print rc.pwm02 # 32
>
> This is a bit hackish, but I would prefer this over a metaclass
> solution. since it does not add
> any hidden magic to your class.

Why is this less hidden or magical than a metaclass ? I'd prefer the
following instead:

from itertools import chain, izip, repeat

def ByteProperties(*names, **defaulted_names):
    def byte_property(name, default):
        return property(lambda self: getattr(self, name, default),
                        lambda self,v: setattr(self, name, v%256))
    def make_class(clsname, bases, dict):
        for name,default in chain(izip(names, repeat(127)),
                                  defaulted_names.iteritems()):
            assert name not in dict # sanity check
            dict[name] = byte_property('_'+name, default)
        return type(clsname,bases,dict)
    return make_class


class RC(object):
    __metaclass__ = ByteProperties('pwm01', pwm02=64)

rc = RC()
print rc.pwm01, rc.pwm02 # 127 64
rc.pwm01 = 1312
print rc.pwm01, rc.pwm02  # 32 64


George




More information about the Python-list mailing list