Python Helpers - Closures
Nov 9, 2019 | Reading Time: 2 min
A script to chain multiple closures in python with example usage.
Closure chaining
1from functools import wraps
2
3
4# A new closure will be returned as a chain of Closures in the incoming list order
5def chain_closures(closure_list=None):
6 if not closure_list:
7 return None
8
9 def chain(f):
10 @wraps(f)
11 def r(*args, **kwargs):
12 newfunc = f
13 for c in reversed(closure_list):
14 newfunc = c(newfunc)
15 return newfunc(*args, **kwargs)
16
17 return r
18
19 return chain
Example
1from functools import wraps
2from closures import chain_closures
3import logging
4
5logger = logging.getLogger()
6
7def x(a):
8 def request_logger(f):
9 @wraps(f)
10 def rlog(*args, **kwargs):
11 logger.info("%s x entry", a)
12 ret = f(*args, **kwargs)
13 logger.info("%s x exit", a)
14 return ret
15
16 return rlog
17
18 return request_logger
19
20
21def y(b):
22 def request_logger(f):
23 @wraps(f)
24 def rlog(*args, **kwargs):
25 logger.info("%s y entry", b)
26 ret = f(*args, **kwargs)
27 logger.info("%s y exit", b)
28 return ret
29
30 return rlog
31
32 return request_logger
33
34
35def z(a, b):
36 c1 = x(a)
37 c2 = y(b)
38
39 def request_logger(f):
40 @wraps(f)
41 def rlog(*args, **kwargs):
42 q = c1(c2(f))
43 logger.info("z entry")
44 ret = q(*args, **kwargs)
45 logger.info("z exit")
46 return ret
47
48 return rlog
49
50 return request_logger
51
52
53def w(a, b, f):
54 c1 = x(a)
55 c2 = y(b)
56 q = c1(c2(f))
57 return q
58
59
60def get_w(a, b):
61 c1 = x(a)
62 c2 = y(b)
63 q = chain_closures([c1, c2])
64 return q
65
66
67def f1(a, b):
68 logger.info("%s %s", a, b)
69 # raise Exception("me except")
70
71
72def smain():
73 c4 = get_w(10, 11)
74 f2 = c4(f1)
75 f2(12, 13)
76 logger.info(f2.__name__)
77
78
79if __name__ == "__main__":
80 logging.basicConfig(format='%(asctime)s - %(message)s', datefmt='%d-%b-%y %H:%M:%S', level=logging.DEBUG)
81 smain()