Using arguments in a decorator
Rotwang
sg552 at hotmail.co.uk
Sat Apr 21 08:46:29 EDT 2012
On 21/04/2012 09:36, Steven D'Aprano wrote:
> [...]
>
> Here is how I would write the above.
>
>
> import functools
>
> def memoise(func):
> """Decorator to memoise a function."""
> cache = {}
> @functools.wraps(func)
> def inner(*args, **kwargs):
> # Make sure keyword args are always looked up in a consistent
> # order by sorting. One minor subtlety: since kwargs cannot
> # have duplicate keys, sorted() will never try to break ties
> # by comparing values. So this will work even for unsortable
> # values like complex numbers.
> kw = tuple(sorted(kwargs.items()))
> try:
> # Cache hit?
> result = cache[(args, kw)]
> except KeyError:
> # Cache miss.
> result = func(*args, **kwargs)
> cache[(args, kw)] = result
> except TypeError:
> # Cache failure; at least one argument is uncacheable.
> result = func(*args, **kwargs)
> # Is the cache too big?
> if len(cache)> 1000:
> # Dump an arbitrary item. A LRU (least recently used) cache
> # would be better, but this will do.
> cache.popitem()
> return result
> # Expose the cache to the outside world.
> inner._cache = cache
> return inner
Thanks. Incidentally, would there be any way to look at the value of
cache if it weren't for the statement inner._cache = cache? For that
matter, I don't understand why 'cache' isn't in inner.__globals__.
> [...]
>> But I don't know how. I know that I can see the default arguments of the
>> original function using func.__defaults__, but without knowing the
>> number and names of func's positional arguments (which I don't know how
>> to find out) this doesn't help me. Any suggestions?
>
>
> http://docs.python.org/release/3.1.5/library/inspect.html?#inspect.getfullargspec
>
>
>>>> def f(a, b=1, *args, c, d=2, **kwargs):
> ... x = 42
> ... return (a,b,c,d,args,kwargs)
> ...
>>>> import inspect
>>>> inspect.getfullargspec(f)
> FullArgSpec(args=['a', 'b'], varargs='args', varkw='kwargs',
> defaults=(1,), kwonlyargs=['c', 'd'], kwonlydefaults={'d': 2},
> annotations={})
Cool; that's not available for Python 2 but it looks like
inspect.getargspec() is and does pretty much the same thing. Also
inspect.getcallargs() does exactly what I need for my decorator. Thanks
very much for your help.
--
Hate music? Then you'll hate this:
http://tinyurl.com/psymix
More information about the Python-list
mailing list