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
@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.
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.
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