FAQ
Hi, all,

This question is in the same context of my two earlier questions. This
question was raised by some python beginners, and I would like to check with
the list to ensure I provide a correct answer.

Here is a code snippet I used to demonstrate the keyword *property*:


class A(object):

def __init__(self):
self.__not_here = 1

def __get_not_here(self):
return self.__not_here

def __set_not_here(self, v):
print "I am called"
self.__not_here = v

not_here = property(lambda self: self.__get_not_here(), lambda self, v:
self.__set_not_here(v))
# not_here = property(lambda self: self.__not_here, lambda self, v:
self.__not_here = v)

So the question: is it possible to use lambda expression at all for the
setter? (As in the last, commented-out line)

Python interpreter will throw an exception right there if I use the last
line ('SyntaxError: lambda cannot contain assignment'). I'd use pass a
setter method anyway.

What is your preferred solution?

--

Tony Kong
*blog:* www.ahwkong.com

/*--*/
Don?t EVER make the mistake that you can design something better than what
you get from ruthless massively parallel trial-and-error with a feedback
cycle. That?s giving your intelligence _much_ too much credit.

- Linus Torvalds
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20110712/4ddcf8cd/attachment.html>

Search Discussions

  • Thomas Jollans at Jul 11, 2011 at 4:23 pm

    On 07/11/2011 05:54 PM, Anthony Kong wrote:
    Hi, all,

    This question is in the same context of my two earlier questions. This
    question was raised by some python beginners, and I would like to check
    with the list to ensure I provide a correct answer.

    Here is a code snippet I used to demonstrate the keyword *property*:


    class A(object):

    def __init__(self):
    self.__not_here = 1

    def __get_not_here(self):
    return self.__not_here

    def __set_not_here(self, v):
    print "I am called"
    self.__not_here = v

    not_here = property(lambda self: self.__get_not_here(), lambda self,
    v: self.__set_not_here(v))
    # not_here = property(lambda self: self.__not_here, lambda self, v:
    self.__not_here = v)

    So the question: is it possible to use lambda expression at all for the
    setter? (As in the last, commented-out line)

    Python interpreter will throw an exception right there if I use the last
    line ('SyntaxError: lambda cannot contain assignment'). I'd use pass a
    setter method anyway.

    What is your preferred solution?
    No, a lambda can only contain an expression, not a statement. This is
    not C, assignments are not expressions.

    As to what I would do:
    There's really no need to use lambdas at all here:

    class A(object):
    def __init__(self):
    self.not_here = 1
    def __get_not_here(self):
    return self.__not_here
    def __set_not_here(self, val):
    self.__not_here = val
    not_here = property(__get_not_here, __set_not_here)

    My favourite way to create properties is of course with decorators:

    class A(object):
    def __init__(self):
    self.not_here = 1

    @property
    def not_here(self):
    return self.__not_here

    @not_here.setter
    def not_here(self, val):
    self.__not_here = val
  • Anthony Kong at Jul 11, 2011 at 4:53 pm
    Thanks again for your input, Thomas.

    I normally prefer

    not_here = property(lambda self: self.__get_not_here(), lambda self, v:
    self.__set_not_here(v))

    than

    not_here = property(__get_not_here, __set_not_here)

    Because it allows me to have a pair getter/setter (when there is a need for
    it). Use of lambda there is ensure derived class of A can provide their
    custom version of getter/setter.


    But decorator! Of course! Thanks for reminding me this.

    In your example, where does '@not_here' come from? (Sorry, this syntax is
    new to me)

    Cheers
    On Tue, Jul 12, 2011 at 2:23 AM, Thomas Jollans wrote:
    On 07/11/2011 05:54 PM, Anthony Kong wrote:
    Hi, all,

    This question is in the same context of my two earlier questions. This
    question was raised by some python beginners, and I would like to check
    with the list to ensure I provide a correct answer.

    Here is a code snippet I used to demonstrate the keyword *property*:


    class A(object):

    def __init__(self):
    self.__not_here = 1

    def __get_not_here(self):
    return self.__not_here

    def __set_not_here(self, v):
    print "I am called"
    self.__not_here = v

    not_here = property(lambda self: self.__get_not_here(), lambda self,
    v: self.__set_not_here(v))
    # not_here = property(lambda self: self.__not_here, lambda self, v:
    self.__not_here = v)

    So the question: is it possible to use lambda expression at all for the
    setter? (As in the last, commented-out line)

    Python interpreter will throw an exception right there if I use the last
    line ('SyntaxError: lambda cannot contain assignment'). I'd use pass a
    setter method anyway.

    What is your preferred solution?
    No, a lambda can only contain an expression, not a statement. This is
    not C, assignments are not expressions.

    As to what I would do:
    There's really no need to use lambdas at all here:

    class A(object):
    def __init__(self):
    self.not_here = 1
    def __get_not_here(self):
    return self.__not_here
    def __set_not_here(self, val):
    self.__not_here = val
    not_here = property(__get_not_here, __set_not_here)

    My favourite way to create properties is of course with decorators:

    class A(object):
    def __init__(self):
    self.not_here = 1

    @property
    def not_here(self):
    return self.__not_here

    @not_here.setter
    def not_here(self, val):
    self.__not_here = val
    --
    http://mail.python.org/mailman/listinfo/python-list


    --

    Tony Kong
    *blog:* www.ahwkong.com

    Don?t EVER make the mistake that you can design something better than what
    you get from ruthless massively parallel trial-and-error with a feedback
    cycle. That?s giving your intelligence *much* too much credit.

    - Linus Torvalds
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-list/attachments/20110712/b0f11c17/attachment.html>
  • Thomas Jollans at Jul 11, 2011 at 5:06 pm
    # On 07/11/2011 06:53 PM, Anthony Kong wrote:
    # But decorator! Of course! Thanks for reminding me this.
    #
    # In your example, where does '@not_here' come from? (Sorry, this syntax
    # is new to me)

    class A(object):
    def __init__(self):
    self.not_here = 1

    @property
    def not_here(self):
    return self.__not_here

    @not_here.setter
    def not_here(self, val):
    self.__not_here = val

    """
    Let's translate that to non-decorator Python:
    """

    class A(object):
    def __init__(self):
    self.not_here = 1

    def _(self):
    return self.__not_here
    not_here = property(_)
    del _

    def _(self, val):
    self.__not_here = val
    not_here = not_here.setter(_)
    del _


    """
    @not_here.setter exists because not_here.setter exists. not_here exists
    since we set it (when the getter/property was set).


    Cheers
    Thomas


    PS: are you sure the lambda self: self.__foo() trick works, with
    subclasses or otherwise? I haven't tested it, and I'm not saying it
    doesn't, but I have a feeling double-underscore name mangling might be a
    problem somewhere down the line?

    """
  • Anthony Kong at Jul 11, 2011 at 5:21 pm

    PS: are you sure the lambda self: self.__foo() trick works, with
    subclasses or otherwise? I haven't tested it, and I'm not saying it
    doesn't, but I have a feeling double-underscore name mangling might be a
    problem somewhere down the line?
    Awesome, Thomas. The trick only works if there is only *one* leading
    underscore in the *method* names.

    The following example works as I expected for the derived class B.

    class A(object):

    def __init__(self):
    self.__not_here = 1

    def _get_not_here(self):
    return self.__not_here

    def _set_not_here(self, v):
    print "I am called"
    self.__not_here = v

    not_here = property(lambda self: self._get_not_here(), lambda self, v:
    self._set_not_here(v))

    class B(A):
    def _set_not_here(self, v):
    print "version B"
    self.__not_here = v


    a = A()
    # print a.__not_here
    print a.not_here
    # a.set_not_here(10)
    a.not_here = 10
    print a.not_here


    b = B()
    print b.not_here
    b.not_here = 70 # print version B
    print b.not_here




    --

    Tony Kong
    *blog:* www.ahwkong.com

    Don?t EVER make the mistake that you can design something better than what
    you get from ruthless massively parallel trial-and-error with a feedback
    cycle. That?s giving your intelligence *much* too much credit.

    - Linus Torvalds
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-list/attachments/20110712/e5c0c2a6/attachment.html>
  • Ian Kelly at Jul 11, 2011 at 5:41 pm

    On Mon, Jul 11, 2011 at 11:21 AM, Anthony Kong wrote:
    Awesome, Thomas. The trick only works if there is only?one?leading
    underscore in the?method?names.
    The following example works as I expected for the derived class B.
    class A(object):
    ? ? def __init__(self):
    ? ? ? ? self.__not_here = 1
    ? ? def _get_not_here(self):
    ? ? ? ? return self.__not_here
    ? ? def _set_not_here(self, v):
    ? ? ? ? print "I am called"
    ? ? ? ? self.__not_here = v
    ? ? not_here = property(lambda self: self._get_not_here(), lambda self, v:
    self._set_not_here(v))
    class B(A):
    ? ? def _set_not_here(self, v):
    ? ? ? ? print "version B"
    ? ? ? ? self.__not_here = v
    It shouldn't. You've still got the name __not_here used in both A and
    B, so that the B version is setting a different attribute than the A
    version (_B__not_here vs. _A__not_here).
  • Anthony Kong at Jul 11, 2011 at 5:56 pm
    So subclass B has no access to __not_here in A after all...

    OK, in one of legacy Python I supported there are a lot of code floating
    around like this. It works OK (in term of business logic and unit test).
    That's probably due to luck :-)

    It also uses a lot of __slot__ = ['attr_a', 'attr_b'...] in class
    definitions to prevent accidental creation of new variables (due to typo for
    example).

    Needless to say it was first written up by programmers of static lang
    background who want to enforce the java/.net behavior... (private variables,
    variable declaration)


    Cheers

    On Tue, Jul 12, 2011 at 3:41 AM, Ian Kelly wrote:

    On Mon, Jul 11, 2011 at 11:21 AM, Anthony Kong
    wrote:
    Awesome, Thomas. The trick only works if there is only one leading
    underscore in the method names.
    The following example works as I expected for the derived class B.
    class A(object):
    def __init__(self):
    self.__not_here = 1
    def _get_not_here(self):
    return self.__not_here
    def _set_not_here(self, v):
    print "I am called"
    self.__not_here = v
    not_here = property(lambda self: self._get_not_here(), lambda self, v:
    self._set_not_here(v))
    class B(A):
    def _set_not_here(self, v):
    print "version B"
    self.__not_here = v
    It shouldn't. You've still got the name __not_here used in both A and
    B, so that the B version is setting a different attribute than the A
    version (_B__not_here vs. _A__not_here).
    --
    http://mail.python.org/mailman/listinfo/python-list


    --

    Tony Kong
    *blog:* www.ahwkong.com

    Don?t EVER make the mistake that you can design something better than what
    you get from ruthless massively parallel trial-and-error with a feedback
    cycle. That?s giving your intelligence *much* too much credit.

    - Linus Torvalds
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-list/attachments/20110712/83340762/attachment.html>
  • Ian Kelly at Jul 11, 2011 at 5:35 pm

    On Mon, Jul 11, 2011 at 10:53 AM, Anthony Kong wrote:
    Thanks again for your input, Thomas.
    I normally prefer
    not_here = property(lambda self: self.__get_not_here(), lambda self,?v:
    self.__set_not_here(v))
    than
    not_here = property(__get_not_here, __set_not_here)
    Because it allows me to have a pair getter/setter (when there is a need for
    it). Use of lambda there is ensure derived class of A can provide their
    custom version of getter/setter.
    The .setter convenience method also makes it a bit easier for derived
    classes to modify getters and setters:

    class Base(object):

    def get_my_property(self):
    return self._my_property

    def set_my_property(self, value):
    self._my_property = value

    my_property = property(get_my_property, set_my_property)


    class Derived(Base):

    def set_my_property(self, value):
    super(Derived, self).set_my_property(convert(value))

    my_property = Base.my_property.setter(set_my_property)
  • Ian Kelly at Jul 11, 2011 at 4:43 pm

    On Mon, Jul 11, 2011 at 9:54 AM, Anthony Kong wrote:
    Hi, all,
    This question is in the same context of my two earlier questions. This
    question was raised by some python beginners, and I would like to check with
    the list to ensure I provide a correct answer.
    Here is a code?snippet?I used to demonstrate the keyword property:
    What Thomas said. But also, please note that "property" is a builtin,
    not a keyword.

    </pedantry>

    Cheers,
    Ian
  • Anthony Kong at Jul 11, 2011 at 4:54 pm
    Good point! Need to get my terminology right. Thanks
    On Tue, Jul 12, 2011 at 2:43 AM, Ian Kelly wrote:
    On Mon, Jul 11, 2011 at 9:54 AM, Anthony Kong wrote:
    Hi, all,
    This question is in the same context of my two earlier questions. This
    question was raised by some python beginners, and I would like to check with
    the list to ensure I provide a correct answer.
    Here is a code snippet I used to demonstrate the keyword property:
    What Thomas said. But also, please note that "property" is a builtin,
    not a keyword.

    </pedantry>

    Cheers,
    Ian
    --
    http://mail.python.org/mailman/listinfo/python-list


    --

    Tony Kong
    *blog:* www.ahwkong.com

    Don?t EVER make the mistake that you can design something better than what
    you get from ruthless massively parallel trial-and-error with a feedback
    cycle. That?s giving your intelligence *much* too much credit.

    - Linus Torvalds
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-list/attachments/20110712/3921b180/attachment.html>
  • John Posner at Jul 11, 2011 at 5:26 pm
    On 2:59 PM, Anthony Kong wrote:

    <snip>
    So the question: is it possible to use lambda expression at all for
    the setter? (As in the last, commented-out line)

    Python interpreter will throw an exception right there if I use the
    last line ('SyntaxError: lambda cannot contain assignment'). I'd use
    pass a setter method anyway.

    What is your preferred solution?
    Anthony, you might take a look at this alternative writeup for
    "property", which I placed on the Python Wiki:

    http://wiki.python.org/moin/AlternativeDescriptionOfProperty

    HTH,
    John

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedJul 11, '11 at 3:54p
activeJul 11, '11 at 5:56p
posts11
users4
websitepython.org

People

Translate

site design / logo © 2022 Grokbase