fsl.utils.memoize

This module provides a handful of decorators which may be used to memoize a function:

memoize Memoize the given function by the value of the input arguments.
Memoize Decorator which can be used to memoize a function or method.
Instanceify This class is intended to be used to decorate other decorators, so they can be applied to instance methods.
memoizeMD5 Memoize the given function.
skipUnchanged This decorator is intended for use with setter functions - a function which accepts a name and a value, and is intended to set some named attribute to the given value.
fsl.utils.memoize.memoize(func=None)

Memoize the given function by the value of the input arguments.

This function simply returns a Memoize instance.

class fsl.utils.memoize.Memoize(*args, **kwargs)

Bases: object

Decorator which can be used to memoize a function or method. Use like so:

@memoize
def myfunc(*a, **kwa):
    ...

@memoize()
def otherfunc(*a, **kwax):
    ...

A Memoize instance maintains a cache which contains {args : value} mappings, where args are the input arguments to the function, and value is the value that the function returned for those arguments. When a memoized function is called with arguments that are present in the cache, the cached values are returned, and the function itself is not called.

The invalidate() method may be used to clear the internal cache.

Note that the arguments used for memoization must be hashable, as they are used as keys in a dictionary.

invalidate(*args, **kwargs)

Clears the internal cache. If no arguments are given, the entire cache is cleared. Otherwise, only the cached value for the provided arguments is cleared.

fsl.utils.memoize.memoizeMD5(func)

Memoize the given function. Whenever the function is called, an md5 digest of its arguments is calculated - if the digest has been previously cached, the previous value calculated by the function is returned.

fsl.utils.memoize.skipUnchanged(func)

This decorator is intended for use with setter functions - a function which accepts a name and a value, and is intended to set some named attribute to the given value.

This decorator keeps a cache of name-value pairs. When the decorator is called with a specific name and value, the cache is checked and, if the given value is the same as the cached value, the decorated function is not called. If the given value is different from the cached value (or there is no value), the decorated function is called.

The invalidate method may be called on a skipUnchanged-decorated function to clear the internal cache. For example:

@skipUnchanged
def setval(name, value):
    # ...

# ...

setval.invalidate()

Note

This decorator ignores the return value of the decorated function.

Returns:True if the underlying setter function was called, False otherwise.
class fsl.utils.memoize.Instanceify(realDecorator)

Bases: object

This class is intended to be used to decorate other decorators, so they can be applied to instance methods. For example, say we have the following class:

class Container(object):

    def __init__(self):
        self.__items = {}

    @skipUnchanged
    def set(self, name, value):
        self.__items[name] = value

Given this definition, a single skipUnchanged() decorator will be created and shared amongst all Container instances. This is not ideal, as the value cache created by the skipUnchanged() decorator should be associated with a single Container instance.

By redefining the Container class definition like so:

class Container(object):

    def __init__(self):
        self.__items = {}

    @Instanceify(skipUnchanged)
    def set(self, name, value):
        self.__items[name] = value

a separate skipUnchanged() decorator is created for, and associated with, every Container instance.

This is achieved because an Instanceify instance is a descriptor. When first accessed as an instance attribute, an Instanceify instance will create the real decorator function, and replace itself on the instance.