Decorator & Pipeline
Story behind
Mr. Xcc has been being fascinated by Functional Programming, he
- wrapped his functions perfectly,
- constructed them into functor to
- pipeline the functions,
1
2
3
4
Slices ms = al | rotate_atoms(get_quat(n, theta)) | make_protein_volume(em.apix, 3, size) |
hydrate_volume() | make_slice_by_ah() | band_limit_slices(0.667);
/* take in al as the functor rotate_atoms()'s input,
return data to functor make_protein_volume() ...*/
in which way he could call nested functions(or functors) quite elegantly .
I got a little bit jealous of the elegance. Attempting to catch the essence of pipeline, I reviewed decorator in python.
Decorator: take func, augment func
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#direct run func
def greet(name):
return "hello " + name
greet_someone = greet
print(greet("xcc"))
# define func inside other func
def greet(name):
def get_message():
return "hello "
return get_message() + name
print(greet("xcc"))
# pass func to other func
def greet(name):
return "hello " + name
def call_func(func, other_name="xcc"):
return func(other_name)
print(call_func(greet))
# func return func
def compose_greet_func(name0):
def get_message(name1):
return name0 + " greet to " + name1
return get_message
print(compose_greet_func("xcc")("xll"))
# decorator: take in a func, do some augmenting and return a greater func
def get_text(name):
return "hello {0}".format(name)
def p_decorator(func):
def func_wrapper(name):
return "inside wrapper:{0}".format(func(name))
return func_wrapper
my_get_text = p_decorator(get_text)
print(my_get_text("xcc"))
# syntactic sugar
def p_decorator(func):
def func_wrapper(name):
return "inside wrapper:{0}".format(func(name))
return func_wrapper
@p_decorator
def get_text(name):
return "hello {0}".format(name)
print(get_text("xcc"))
Pipeline decorator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# take in original function, return a class, which
# 0.init with args&kwargs,
# 1.its __rrshift__() take parameter from >>,
# then return mark(parameter, args, kwargs))
def pipe(original):
class PipeInto(object):
data = {'function': original}
def __init__(self, *args, **kwargs):
# *args is to unpack
self.data['args'] = args
self.data['kwargs'] = kwargs
# now args and kwargs are tuple and dict
print("args:", args)
def __rrshift__(self, parameter):
return self.data['function'](
parameter,
*self.data['args'],
**self.data['kwargs'])
return PipeInto
@pipe
def mark(parameter, score):
if parameter == "xcc":
return parameter + " love xll: " + str(score)
if parameter == "xll":
return parameter + " love xcc: " + str(score)
print("xcc">>mark(10) )
# "xcc" here is the parameter, where as 10 belongs to args.
# In this way, parameter and args are taken separately
# from the left side of >> and the ()