If \$f\$ is a numerical function and \$n\$ is a positive integer, then we can form the \$n\$th repeated application of \$f\$, which is defined to be the function whose value at \$x\$ is \$f(f(...(f(x))...))\$. For example, if \$f\$ adds 1 to its argument, then the \$n\$th repeated application of \$f\$ adds \$n\$. Write a function that takes as inputs a function \$f\$ and a positive integer \$n\$ and returns the function that computes the \$n\$th repeated application of \$f\$:
def repeated(f, n): """Return the function that computes the nth application of f. f -- a function that takes one argument n -- a positive integer >>> repeated(square, 2)(5) 625 >>> repeated(square, 4)(5) 152587890625 """ "*** YOUR CODE HERE ***"
Below is the solution:
from operator import mul
def repeated(f, n):
    """Return the function that computes the nth application of f.
    f -- a function that takes one argument
    n -- a positve integer
    >>> repeated(square, 2)(5)
    625
    >>> repeated(square, 4)(5)
    152587890625
    """
    def g(x):
        i = 1
        while i <= n:
            x, i = f(x), i + 1
        return x
    return g
def square(x):
    return mul(x, x)
print(repeated(square,4)(2))
I've tested it and it looks fine.
Can I optimise this code better? Do you think I can use better names instead of i & g?