Python :: defprop – a very simple idiom for defining properties

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…

This entry was posted in Python. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *