Decorators can be used to load data structures with a function. Using this technique can reduce the 'lots of declarations; large table definition; startup' structure of some larger programs. The insight is remembering that a decorator can return the original function unchanged.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | conversions = {} # the data structure -- a dict-of-dicts
def converter(source, dest):
'''A decorator that fills the conversions table with entries'''
def decorate(function):
'''Update the conversions table and return the original'''
try:
previous = conversions[source][dest]
except KeyError:
conversions.setdefault(source, {})[dest] = function
return function
raise ValueError, 'Two conversions from %r to %r: %r and %r' % (
source, dest, getattr(previous, '__name__', previous),
getattr(function, '__name__', function))
return decorate
@converter('inch', 'feet')
def tofeet(measure):
return 12 * measure
@converter('feet', 'inch')
def toinch(measure):
return measure / 12.
# ...
# converter can be used as a non-decorator to load other values.
converter('feet', 'hectare')(None)
print conversions['feet']['inch'](123)
print conversions['inch']['feet'](123)
print conversions['feet']['hectare']
|
This recipe uses decorators, a feature of python 2.4 or greater.
I hope you get the idea by the code. We avoid defining a lot of conversions and following those declarations by the declaration of a large dictionary. You can certainly use decorators like this to make to make hard-to-read code, but by placing the identifying information with the declaration, you can make some code much clearer.
Admitedly, this _still_ doesn't make the old English system of measurement anything more than barely palatable.
Well, hectares aren't an English measure, to be sure... ;)
Generic functions. This is similar to generic functions (PyProtocol's dispatch: http://peak.telecommunity.com/DevCenter/CombiningResults), which might look like: