[Edu-sig] Design patterns

Kirby Urner urnerk at qwest.net
Sun Aug 21 21:01:55 CEST 2005

> def writeprop(viewvar):
>      '''decorator makes a property from access and a write method'''
>      def view(self):
>          return getattr(self, viewvar)
>      def buildprop(writemethod):
>          return property(view, writemethod)
>      return buildprop

Pretty fancy Scott and again, highly worthy of study.  

An element in this design pattern is using a function (writeprop) to build
the decorator function (buildprop) that'll transform the following def (e.g.
def c).

Scott used the same technique when he enhanced my hypertoon program (a
VPython cartoon generator) with decorator syntax.

def f2:

uses f1(args) to build a function which then takes f2 as its argument,
rebinding the result to f2, i.e. f2 = (f1(args))(f2), where f1(args) by
itself returns a callable.

In this case, buildprop returns a curried property function (curried in that
the 'view' method is already bound, defined in terms of getattr).

The decorator returns a function the effect of which is equivalent to 'c =
property(view, c)' i.e. c-the-function goes in as buildprop's writemethod
and is rebound to make c a property.

>      @writeprop('_c')
>      def c(self, v):
>          self.check(v, self.a, self.b)
>          self._c = v
>          self._reset()

Here's a similar base triangle class without the decorators:

class BaseTriangle2(object):
     def check(klass, a, b, c):
         '''Check three lengths for suitability as triangle sides'''
         if a >= b + c:
             raise ValueError, 'Too long: %s >= %s + %s' % (a, b, c)
         if a <= abs(b - c):
             raise ValueError, 'Too short: %s <= abs(%s - %s)' % (a, b,c)

     def __init__(self, a, b, c):
         self.check(a, b, c)
         self._a = a
         self._b = b
         self._c = c

     def __repr__(self):
         return '%s(%s, %s, %s)' % (self.__class__.__name__,
                                    self.a, self.b, self.c)

     def _reset(self):
         '''Called whenever the sides of the triangle change'''

     def _seta(self, v):
         self.check(v, self.b, self.c) # fixed typo in original
         self._a = v
     def _setb(self, v):
         self.check(v, self.a, self.c)
         self._b = v

     def _setc(self, v):
         self.check(v, self.a, self.b)
         self._c = v

     def _geta(self):  return self._a
     def _getb(self):  return self._b
     def _getc(self):  return self._c

     a = property(_geta, _seta)
     b = property(_getb, _setb)
     c = property(_getc, _setc)


More information about the Edu-sig mailing list