Enhanced property decorator

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Tue Sep 2 03:26:36 EDT 2008


En Mon, 25 Aug 2008 22:45:36 -0300, Daniel <millerdev at gmail.com> escribió:

> I've often been frustrated by the inability of the built-in property
> descriptor to handle anything other than a read-only property when
> used as a decorator. Furthermore, read/write/delete properties take
> their doc-string and property definition at a non-intuitive and
> awkward place (after the getter/setter/delter functions). The
> following are three possible solutions to this problem (inspired by
> message http://groups.google.com/group/comp.lang.python/msg/9a56da7ca8ceb7c7).
> I don't like the solution in that thread because it uses apply() which
> will go away in Python 3.
>
> Solution 1: new built-in function/descriptor
>
> def prop(func):
>     funcs = dict(enumerate(func()))
>     return property(funcs[0], funcs[1], funcs.get(2), func.__doc__)
>
> class Test(object):
>     @prop
>     def test():
>         """test doc string"""
>         def fget(self):
>             return self._test
>         def fset(self, value):
>             self._test = value
>         def fdel(self):
>             del self._test
>         return fget, fset, fdel
>
> Of course the name (prop) could be changed... I couldn't think of
> anything more concise.
>
> Pros:
> (1) encapsulation of property logic inside function namespace,
> preventing clutter in class namespace.
> (2) doc string appears in a more natural place, before getter/setter/
> delter logic, as in classes and functions.
>
> Cons:
> (1) additional built-in name.
> (2) duplication/boilerplate in return line (DRY violation).

(Some days late, sorry...) I like the variant below, based on your code. It avoids issue (2) by using locals(). Works with Python 3.0 too - and don't use tricks like sys._getframe or sys.settrace:

def defproperty(func):
   impls = func()
   return property(doc=func.__doc__, **impls)

class Test(object):
   @defproperty
   def test():
       """test doc string"""
       def fget(self):
           return self._test
       def fset(self, value):
           self._test = value
       def fdel(self):
           del self._test
       return locals()

-- 
Gabriel Genellina




More information about the Python-list mailing list