TurnKey Linux Virtual Appliance Library

Python property gotcha

If you like using a single getter/setter function for your properties, watch out if using None for the default. If you do that you won't be able to set your property to None!

Example code and workaround...


class CantSetNone(object):
    def __init__(self):
        self._test = None

    def test(self, val=None):
        print "test(%s)" % `val`
        if val is None:
            return self._test
        else:
            self._test = val
    test = property(test, test)

class UNDEFINED:
    pass

class CanSetNone(object):
    def __init__(self):
        self._test = None

    def test(self, val=UNDEFINED):
        print "test(%s)" % `val`
        if val is UNDEFINED:
            return self._test
        else:
            self._test = val
    test = property(test, test)

You can get future posts delivered by email or good old-fashioned RSS.
TurnKey also has a presence on Google+, Twitter and Facebook.

Comments

the shorter version

The shorter version of sentinel declaration is

UNDEFINED = object()

But why?

Just so that I understand, what is the point in this example of having the get and set in the same method?

For languages which don't have properties I can understand (ie in javascript jQuery has val() and val(someStuff as methods on inputfields), but just I can't see the need in Python since properties serve the same purpose.

re: Python property gotcha

This is the first idea that came to me. YMMV.

class CanSetNone(object):
    def __init__(self):
        self._test = None

    def test(self, *args):
        if args:
            self._test = args[0]
        else:
            return self._test
    test = property(test, test)

Simpler solution

Given your implementation, this is simpler:

class PythonIsNotJava(object):
    def __init__(self):
        self.test = None

If you are going to do something besides setting and getting in your setter and getter, then this is more explicit and avoids the problem:

class PythonProperty(object):
    def __init__(self):
        self._test = None
    def _get_test(self):
        return self._test
    def _set_test(self, val):
        self._test = val
    test = property(_get_test, _set_test)

Sorry, but this has little to

Sorry, but this has little to do with properties but with choosing right sentinels in default arguments.

WE WANT Undefined!!

WE WANT Undefined!!

Post new comment

The content of this field is kept private and will not be shown publicly. If you have a Gravatar account, used to display your avatar.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <p> <span> <div> <h1> <h2> <h3> <h4> <h5> <h6> <img> <map> <area> <hr> <br> <br /> <ul> <ol> <li> <dl> <dt> <dd> <table> <tr> <td> <em> <b> <u> <i> <strong> <font> <del> <ins> <sub> <sup> <quote> <blockquote> <pre> <address> <code> <cite> <strike> <caption>

More information about formatting options

Leave this field empty. It's part of a security mechanism.
(Dear spammers: moderators are notified of all new posts. Spam is deleted immediately)