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
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to