Most attempts at making it easier to define properties in Python seem to quickly descend into metaclass obscurity. Metaclasses can surely solve the problem for an appropriate definition of solve, but “Explicit is better than implicit”, and “Simple is better than complex,” so none of the metaclass solutions (mine included) have had great appeal. It’s always fun to visit the Cookbook, and today I found a great recipe from Sean Ross at http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/205183.
To recap, the traditional way of defining properties looks something like this
class MyClass(object): def __init__(self): self._foo = "foo" def getfoo(self): return self._foo def setfoo(self, value): self._foo = value def delfoo(self): del self._foo foo = property(getfoo, setfoo, delfoo, "property foo's doc string")
All the getters and setters pollute your class namespace (think about adding a bar property), visually there is no Pythonic grouping of the code that belongs to the property, and you don’t really know that it’s going to be a property until the end.
At the end of the recipe Sean says that if decorators are accepted (they were) his idiom would be even better, so here’s my attempt:
# a simple decorator def defprop(doc): def _defprop(fn): return property(doc=doc, **fn()) return _defprop class MyClass(object): def __init__(self): self._x = 42 @defprop("The answer to life the universe and Everything") def foo(): def fget(self): return self._x def fset(self, v): self._x = v return locals()
Overall, I think it doesn’t suck too bad. The name defprop is based on the fact that def is an abbreviation also and property is taken.
Update: turns out I’ve found it easier to not use the decorator, just like the recipe mentioned above:
class MyClass(object): def __init__(self): self._x = 42 def foo(): def fget(self): return self._x def fset(self, v): self._x = v return locals() foo = property(**foo())
it’s an easy idiom to remember, easier than writing the property from scratch, and apparantly easier than figuring out where to put a property so that it will be available everywhere I happen to be…