compose = lambda f, g: lambda x: f(g(x))
# So now if I go:
def S(x): return x * x
def R(x): return x + (1/2)*x
# I can then build new functions:
print("="*10)
H = compose(S, R)
J = compose(R, S)
print(H(10))
print(J(10))
class Compose:
"""make function composible with multiply"""
def __init__(self, f):
self.func = f
def __mul__(self, other):
return Compose(lambda x: self(other(x)))
def __call__(self, x):
return self.func(x)
S = Compose(S) # <--- this is what @decorator does
R = Compose(R) # <--- R is replaced with its proxy
print("="*10)
# multiply to compose
H = S * R
J = R * S
print(H(10))
print(J(10))
print("="*10)
# decorate to compose
@Compose
def addK(s):
return s + "K"
@Compose
def addM(s):
return s + "M"
# addM and addK are actually Compose type thanks to decorator
fun_func = addM * addM * addM * addM * addK # multiply!
print("Test decorated versions: ", fun_func("O"))