http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/205183 idiom

George Sakkis george.sakkis at gmail.com
Tue Mar 18 14:20:58 EDT 2008


On Mar 18, 6:03 am, Gabriel Rossetti
<gabriel.rosse... at mydeskfriend.com> wrote:
> Carsten Haese wrote:
> > On Tue, 2008-03-18 at 09:06 +0100, Gabriel Rossetti wrote:
>
> >> Hello,
>
> >> I am reading core python python programming and it talks about using the
> >> idiom
> >> described on
> >>http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/205183.
>
> >> I'm using python 2.5.1 and if I try :
>
> >> class MyClass(object):
> >>     def __init__(self):
> >>         self._foo = "foo"
> >>         self._bar = "bar"
>
> >>     @property
> >>     def foo():
> >>         doc = "property foo's doc string"
> >>         def fget(self):
> >>             return self._foo
> >>         def fset(self, value):
> >>             self._foo = value
> >>         def fdel(self):
> >>             del self._foo
> >>         return locals()  # credit: David Niergarth
>
> >>     @property
> >>     def bar():
> >>         doc = "bar is readonly"
> >>         def fget(self):
> >>             return self._bar
> >>         return locals()
>
> >> like suggested in the book (the decorator usage) I get this :
>
> >>    >>> a=MyClass()
> >>    >>> a.foo
> >>    Traceback (most recent call last):
> >>      File "<stdin>", line 1, in <module>
> >>    TypeError: foo() takes no arguments (1 given)
>
> >> but if I write it just like on the web page (without the decorator, using "x = property(**x())" instead) it works :
>
> >>    >>> a = MyClass()
> >>    >>> a.foo
> >>    'foo'
>
> >> does anyone have an idea as of why this is happening?
>
> > You're mixing two completely different approaches of building a
> > property. If that code is actually in the book like that, that's a typo
> > that you should mention to the author.
>
> > The @property decorator can only be used to turn a single getter
> > function into a read-only attribute, because this:
>
> >    @property
> >    def foo(...):
> >       ...
>
> > is the same as this:
>
> >    def foo(...):
> >       ...
> >    foo = property(foo)
>
> > and calling property() with one argument builds a property that has just
> > a getter function that is the single argument you're giving it.
>
> > The recipe you're referring to uses a magical function that returns a
> > dictionary of getter function, setter function, deleter function, and
> > docstring, with suitable key names so that the dictionary can be passed
> > as a keyword argument dictionary into the property() constructor.
> > However, that requires the magical foo=property(**foo()) invocation, not
> > the regular decorator invocation foo=property(foo).
>
> > HTH,
>
> I was able to get it t work with the decorator by doing this :
>
> def MyProperty(fcn):
>     return property(**fcn())
>
> and using it like this :
>
> class MyClass(object):
>    def __init__(self):
>        self._foo = "foo"
>        self._bar = "bar"
>
>    @MyProperty
>    def foo():
>        doc = "property foo's doc string"
>        def fget(self):
>            return self._foo
>        def fset(self, value):
>            self._foo = value
>        def fdel(self):
>            del self._foo
>        return locals()  # credit: David Niergarth
>
>    @MyProperty
>    def bar():
>        doc = "bar is readonly"
>        def fget(self):
>            return self._bar
>        return locals()
>
> Cheers,
> Gabriel

Also check out a related recipe that doesn't require returning
locals() explicitly: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/410698

George



More information about the Python-list mailing list