Ian Bicking: the old part of his blog

property decorator

For some reason it never occurred to me that you could use property() as a decorator. Of course, if you want to use getters and setters you can't, but for the (fairly common) case when you have a function that you want to turn into a read-only attribute, it works great:

class Foo(object):
    @property
    def bar(self):
        return <calculated value>

Huh. Seems obvious now.

Update: these days this is built in, and fancier. Try:

class Velocity(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
    @property
    def speed(self):
        return math.sqrt(self.x**2 + self.y**2)
    @speed.setter
    def speed(self, value):
        angle = math.atan2(self.x, self.y)
        self.x = math.sin(angle) * value
        self.y = math.cos(angle) * value
    @speed.deleter
    def speed(self):
        self.x = self.y = 0

That is, @property is both a decorator, and creates a decorator, that can be used to add a setter and deleter to the getter. Note the name of the second two functions is insignificant.

Created 07 Jul '05

Comments:

source
For getters and setters, I like this:

class Foo(object):
    @apply
    def bar():
        def fget(self):
            return self.whatever
        def fset(self, value):
            self.whatever = value
        return property(**locals())

fdel and doc can be added if needed.
And, if the "**locals()" seems too magical "fget, fset" can be substituted.
# Benji York

I can't get myself to like any of those kinds of recipes for getters and setters. In SQLObject I added something to the metaclass to automatically turn _get_* and _set_* functions into getters and setters, and the Wareweb I changed the convention to *__get, since that seems more obviously special (code for that is in paste.util.classinit)

# Ian Bicking

A clean namespace is good, but a namespace can be _too_ clean.

Having '_get_something' '_set_something' available is usually nice.

# anonymous

I'd prefer camel cased versions, and preferably, set the decorator myself. (Like the python 2.3 notation)

# rboerma