The PyCON 06 lightning talk I didn't give: Properties
=====================================================
At EuroPython 2004, Guido made us vote on the Python decorator syntax.
I voted against what became the current syntax at the time. Today I
rather like it, not only because other languages also use it. I think
it doesn't read as badly as I anticipiated. It especially makes
things like dynamic properties much more readable:
>>> class JamesBrown(object):
... @property
... def feel(self):
... return self._feel
There's one wart, though. There's no easy syntax for writable (and
delable) properties. The traditional way would be this:
>>> class JamesBrown(object):
... def _getFeel(self):
... return self._feel
... def _setFeel(self, feel):
... self._feel = feel
... feel = property(_getFeel, _setFeel)
This isn't even half as nice to read as the decorator spelling from
above. It also leaves setters and getters behind in the class which
creates unnecessary clutter.
Of course, there's a way to use a decorator if you **really** want:
>>> class JamesBrown(object):
... @apply
... def feel():
... def get(self):
... return self._feel
... def set(self, feel):
... self._feel = feel
... return property(get, set)
Sure, this doesn't leave setters and getters behind and it *is* more
compact than the previous example. However, apart from the fact that
I find this just plain sick :), it still doesn't read top-down. The
fact that a property is created occurs on the last line of the whole
beast. Also, `Python 3k `_
`won't have apply `_...
Read & write properties
-----------------------
So, I was looking for a solution and came up with something a few
weeks before PyCON 06 called `read & write properties
`_. This is what
it looks like:
>>> from rwproperty import getproperty, setproperty
>>> class JamesBrown(object):
... @getproperty
... def feel(self):
... return self._feel
... @setproperty
... def feel(self, feel):
... self._feel = feel
Of course, there's also ``@delproperty`` to provide deleters. The
order in which all of these are defined doesn't matter. Internally,
they simply return ``property`` objects based on already defined
``property`` objects. They do that with the ``sys._getframe(1)``
hack, a popular but sometimes frowned-upon hack...
All in all, it's no rocket science (61 LOC + 140 lines of doctest),
after all, it's about cosmetics anyways. I was rather satisfied with
my creation and prepared a lightning talk for PyCON 06. I didn't give
it in front of the large crowd because I decided to talk about
internet censorship in China instead.
Class properties
----------------
I did manage to give my lightning talk some time during the sprints
after the conference, though. Jim Fulton and Ian Bicking were around
so we were goofing around with even different syntaxes. One
particular thing that just popped up (I absolutely have no idea who's
idea it was exactly) was a syntax like this:
>>> from classproperty import classproperty
>>> class JamesBrown(object):
... class feel(classproperty):
... def __get__(self):
... return self._feel
... def __set__(self, feel):
... self._feel = feel
That felt very Pythonic. And hey, it didn't even need any decorators
at all! That isn't to say that this always is an advantage, but it's
sure nice to note.
I think Ian even quickly hacked this together while the rest of us had
already turned to Shiner Bock and whatever beer we had brought with us
from the liquor store. `Today I gave it a shot
`_. As you can
imagine, this implementation is even shorter, thanks to metaclasses
(15 LOC, 101 lines of doctest).
Conclusion
----------
I like both of my inventions, but for some reason I prefer the latter
one. Class properties feel more Pythonic, I guess because you
actually end up spelling out the property API (``__get__``,
``__set__``). There's also less to import. Of course, it'd be nice
if you wouldn't have to import it at all... PEP4000, here we come!
Now seriously, it seems almost like waste to spend a whole blog entry
babbling about something so insignificant. But isn't that something
we like about Python so much: that we actually spend some time
thinking about making solutions pretty and aesthetic?