4

I know how to compose two functions by taking two functions as input and output its composition function but how can I return a composition function f(f(...f(x)))? Thanks

def compose2(f, g):
    return lambda x: f(g(x))

def f1(x):
    return x * 2
def f2(x):
    return x + 1

f1_and_f2 = compose2(f1, f2)
f1_and_f2(1)
Garfield
  • 182
  • 7

4 Answers4

5

You use a loop, inside a nested function:

def compose(f, n):
    def fn(x):
        for _ in range(n):
            x = f(x)
        return x
    return fn

fn will be have closure that retains references to the f and n that you called compose with.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
  • @Pencilcaseman I do believe that that's just a simple loop rather than a recursion, as no function here calls *itself* – Gabi Jun 01 '22 at 10:27
  • Hahahaha you’re right. Turns out I was the inexperienced one… I’ll delete that comment. Thanks for pointing it out! – Pencilcaseman Jun 02 '22 at 11:15
1

if you want to make it one line composition,

then try this,

def f1(x):
    return x * 2
def f2(x):
    return x + 1

>>> out = lambda x, f=f1, f2=f2: f1(f2(x)) # a directly passing your input(1) with 2 function as an input (f1, f2) with default so you dont need to pass it as an arguments
>>> out(1)
4
>>> 

>>> def compose(f1, n):
...   def func(x):
...     while n:
...       x = f1(x)
...       n = n-1
...     return x
...   return func

>>> d = compose(f1, 2)
>>> d(2)
8
>>> d(1)
4
>>> 
Mohideen bin Mohammed
  • 18,813
  • 10
  • 112
  • 118
  • Thanks, may I know how to write a function that takes *f1* and *n* as input and outputs *f1(f1(...f1(x))* function? where *f1* is composed *n* times. – Garfield Nov 14 '19 at 06:37
1

Note this is mostly just copied from https://stackoverflow.com/a/16739439/2750819 but I wanted to make it clear how you can apply it for any one function n times.

def compose (*functions): 
    def inner(arg): 
        for f in reversed(functions): 
            arg = f(arg) 
        return arg 
    return inner

n = 10
def square (x): 
    return x ** 2

square_n = [square] * n
composed = compose(*square_n)
composed(2)

Output

179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
Kent Shikama
  • 3,910
  • 3
  • 22
  • 55
0

you can use functools.reduce:

from functools import reduce

def compose(f1, f2):
    return f2(f1) 

reduce(compose, [1, f2, f1]) # f1(f2(1))

output:

4

if you want to compose same function n times:

n = 4
reduce(compose, [1, *[f1]*n]) # f1(f1(f1(f1(1))))

output:

16
kederrac
  • 16,819
  • 6
  • 32
  • 55