instance variable weirdness

Felipe Almeida Lessa felipe.lessa at gmail.com
Fri Apr 14 14:20:06 EDT 2006


Em Sáb, 2006-04-15 às 04:03 +1000, Steven D'Aprano escreveu:
> Sometimes you want the default to mutate each time it is used, for example
> that is a good technique for caching a result:
> 
> def fact(n, _cache=[1, 1, 2]):
>     "Iterative factorial with a cache."
>     try:
>         return _cache[n]
>     except IndexError:
>         start = len(_cache)
>         product = _cache[-1]
>         for i in range(start, n+1):
>             product *= i
>             _cache.append(product)
>         return product

I prefer using something like this for the general case:

def cached(function):
    """Decorator that caches the function result.

    There's only one caveat: it doesn't work for keyword arguments.
    """
    cache = {}
    def cached_function(*args):
        """This is going to be replaced below."""
        try:
            return cache[args]
        except KeyError:
            cache[args] = function(*args)
            return cache[args]
    cached_function.__doc__ = function.__doc__
    cached_function.__name__ = function.__name__
    return cached_function



And for this special case, something like:

def fact(n):
    "Iterative factorial with a cache."
    cache = fact.cache
    try:
        return cache[n]
    except IndexError:
        start = len(cache)
        product = cache[-1]
        for i in range(start, n+1):
            product *= i
            cache.append(product)
        return product
fact.cache = [1, 1, 2]



This may be ugly, but it's less error prone. Also, we don't expose the
cache in the function's argument list.

-- 
Felipe.




More information about the Python-list mailing list