import functools
This can cache the result of a function, such that further call can be returned directly. Internally, it use a dict to store corresponding results, so all the arguments must be hashable. Such feature is especially useful in dynamicall programming context.
@functools.lru_cache(maxsize=200) # maxsize can be set to None, where infinite results are cached, caution!
def add1(n):
print("caculating...")
return n+1
add1(1), add1(2), add1(1), add1(3), add1(3)
caculating... caculating... caculating...
(2, 3, 2, 4, 4)
add1.cache_info() # you can even check the hit rate!!
CacheInfo(hits=2, misses=3, maxsize=200, currsize=3)
add1.cache_clear() # clean the cache
add1(1)
caculating...
2
make partial functions
def add(x,y):
print(f"{x}+{y}")
return x+y
add1 = functools.partial(add,2)
add1(1)
2+1
3
The usage of reduce is evident, and no further explanation here
functools.reduce(add, [1,2,3,4,5])
1+2 3+3 6+4 10+5
15
functools.reduce(add, [1,2,3,4,5], 10) # the third argument is the start point of reduce
10+1 11+2 13+3 16+4 20+5
25
function overload based on the type of the first argument
@functools.singledispatch
def show(arg, n): # the default function
print("default")
@show.register(int)
def show_int(arg, n): # note the function name here is not the same as show
return arg+n
@show.register(list)
def show_list(arg, n):
return [a+n for a in arg]
show.register(float, lambda arg, n: arg+n) # the overload function can also register directly
<function __main__.<lambda>>
show(2,3), show(2.2,1), show([1,2,3], 0)
(5, 3.2, [1, 2, 3])
show((2,3),1)
default
show.dispatch(set), show.dispatch(list)
(<function __main__.show>, <function __main__.show_list>)
Maybe the most used one in this module, used in definition of new decorators, such that relevant attrs of wrapper function keep the original form
# define a decorator without using wraps
def log(f):
def wrapper(*args, **kws):
print(f"call {f.__name__}")
return f(*args, **kws)
return wrapper
@log
def add(a, b):
return a+b
add(1,2) ## the log decorator works
call add
3
add.__name__ ## but the function name is not as expected, we hope the name is still add
# which make the decorator transparency
'wrapper'
# try define the same decorator with wrap tool
def log(f):
@functools.wraps(f)
def wrapper(*args, **kws):
print(f"call {f.__name__}")
return f(*args, **kws)
return wrapper
@log
def add(a, b):
return a+b
add(1,2)
call add
3
add.__name__ ## now the relevant attrs of add is correct again
'add'