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

Discussion in 'Python' started by Gabriel Rossetti, Mar 18, 2008.

  1. 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
     
    Gabriel Rossetti, Mar 18, 2008
    #1
    1. Advertising

  2. On Mar 18, 6:03 am, Gabriel Rossetti
    <> 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
     
    George Sakkis, Mar 18, 2008
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Raaijmakers, Vincent \(GE Infrastructure\)

    Looking for cookbook/recipe generating multipart web data

    Raaijmakers, Vincent \(GE Infrastructure\), Apr 5, 2004, in forum: Python
    Replies:
    0
    Views:
    288
    Raaijmakers, Vincent \(GE Infrastructure\)
    Apr 5, 2004
  2. dw

    ASPN Python Recipe in CHM

    dw, Jul 23, 2004, in forum: Python
    Replies:
    0
    Views:
    350
  3. dody
    Replies:
    4
    Views:
    380
    Tony C
    Aug 26, 2004
  4. Gabriel Rossetti
    Replies:
    0
    Views:
    353
    Gabriel Rossetti
    Mar 18, 2008
  5. Gabriel Rossetti
    Replies:
    1
    Views:
    321
    wesley chun
    Mar 19, 2008
Loading...

Share This Page