Decorator factory#
Recall the version of the decorator cache that relied on a global variable:
MAXSIZE = 1000
def cache(f):
cache = {}
def cached_f(*args):
if args not in cache:
if len(cache) >= MAXSIZE:
cache.popitem()
cache[args] = f(*args)
return cache[args]
return cached_f
Now, instead of using MAXSIZE as a global variable, indent the whole code and put it inside a function called cache_factory:
def cache_factory(maxsize):
def cache(f):
cache = {}
def cached_f(*args):
if args not in cache:
if len(cache) >= maxsize:
cache.popitem()
cache[args] = f(*args)
return cache[args]
return cached_f
The function cache_factory accepts an integer for the maximum cache size and then creates a working decorator cache as you’ve seen before.
Now, for the function cache_factory to be fully working, it must return the decorator cache that it built:
def cache_factory(maxsize):
def cache(f):
cache = {}
def cached_f(*args):
if args not in cache:
if len(cache) >= maxsize:
cache.popitem()
cache[args] = f(*args)
return cache[args]
return cached_f
return cache
Now, the function cache_factory can be used to build caches with different maximum sizes.
If you want to decorate fn1 with a cache of maximum size 1,000 and fn2 with a cache of maximum size 2,000, you can do so:
cache1000 = cache_factory(1000)
cache2000 = cache_factory(2000)
@cache1000
def fn1(*args):
...
@cache2000
def fn2(*args):
...
Since cache_factory is a cache factory, you can use it to create two different cache decorators (cache1000 and cache2000) and then you can apply those.
This works!