[Python-Dev] PEP 318: Let's propose some useful built-in
decorators
Michael Chermside
mcherm at mcherm.com
Mon Apr 5 10:03:46 EDT 2004
Guido writes:
> While I ponder the decorator syntax, let's propose some built-in
> decorators.
[...]
> Proposals for other standard decorators are welcome!
memoized -- Encloses the function in a wrapper which provides automatic
memoization. Provides two different uses. The simple use is just this:
def fibonacci(n) [memoized()]:
if n == 0: return 0
elif n == 1: return 1
else return fibonacci(n-1) + fibonacci(n-2)
...which automatically memoizes all results. For advanced users who
want to limit memory use, there's this:
def fibonacci(n) [memoized(cache_size=25)]:
[...]
... which will save only the 25 most-recently-used values.
Here... I'll try to implement it, since I want to play around with
writing a decorator which takes arguments. I'll see if I can do so in
a highly readable manner:
# WARNING... Untested code follows!
def memoized(cache_size=None):
if cache_size is None:
# No cache size limits, so just store the values in a hash
def memoize_decorator(f):
memo_cache = {}
def wrapper_function(*args, **kwargs):
if memo_cache.has_key((args, kwargs)):
return memo_cache[(args, kwargs)]
else:
value = f(*args, **kwargs)
memo_cache[(args, kwargs)] = value
elif not memo_cache_full:
return value
return wrapper_function
else:
# cache_size is given, so we need a LRU cache.
# This currently uses a dirt-simple LRU cache... a list
# of (key, value) pairs with new items added to the end.
# Performance could be improved with a fancier data
# structure.
def memoize_decorator(f):
memo_cache = []
def wrapper_function(*args, **kwargs):
for key, value in memo_cache:
if key == (args, kwargs):
# Found it in the cache! Move to end of list.
memo_cache.remove( ((args, kwargs), value) )
memo_cache.append( ((args, kwargs), value) )
# Not found in cache... must calculate
value = f(*args, **kwargs)
memo_cache.append( ((args, kwargs), value) )
if len(memo_cache) > cache_size:
memo_cache.pop(0)
return value
return wrapper_function
return memoize_decorator
Hmm.... somewhat awkward, but readable. Nested function definitions and
nested scoping rules make this much easier than otherwise. Nevertheless,
a class-based approach might have worked better.
-- Michael Chermside
More information about the Python-Dev
mailing list