Recursive function using lambda expression

2019-08-11 19:45发布

I need to create a recursive function repeat which takes in a function and uses the function n number of times with the value of x. Here's an iterative version that explains my issue a bit more in detail.

def repeat(fn, n, x):
    res = x
    for i in range(n):
        res = fn(res)
        print(res)
    return res

print(repeat(lambda x: x**2, 3, 3)) returns 6561

First it takes 3^2, then 3^2^2 which is 81 then again 3^2^2^2 = 6561. How can i make this recursive so it can work like this.

square_three_times = repeat(lambda x: x**2, 3)
print(square_three_times(3)) return 6561

I have tried something like this but im really lost and not sure what to do.

def repeat(fn, n):
    if n == 1:
        return fn(n):
    else:
        def result(x):
            return fn(n)
    return repeat(fn,result(x))

This obviously wouldnt work since the recursion would keep going forever. But im not sure how i should write this code since i first need to calculate 3^2 before taking the next step 9^2 and so on.

2条回答
倾城 Initia
2楼-- · 2019-08-11 20:30

You can define this very simply in terms of your old repeat function:

repeat_new = lambda fn, n: lambda x: repeat(fn, n, x)

square_three_times = repeat_new (lambda x: x**2, 3)
print(square_three_times(3))
查看更多
相关推荐>>
3楼-- · 2019-08-11 20:36

First, you've got the base case wrong:

if n == 1:
    return fn

After all, repeat(fn, 1) is just a function that applies fn once—that's fn.

Now, if the base case is when n == 1, the recursive case is almost always going to be something where you pass n - 1 to yourself.

So, what's the difference between repeat(fn, n) and repeat(fn, n-1)? If you can't figure it out, expand a simple case out in your head or on paper:

repeat(fn, 3)(x): fn(fn(fn(x)))
repeat(fn, 2)(x): fn(fn(x))

And now it's obvious: repeat(fn, n) is the same thing as fn(repeat(fn, n-1)), right? So:

else:
    def new_fn(x):
        return fn(repeat(fn, n-1)(x))
    return new_fn

However, as filmor points out in the comments, it would be easier to use partial here:

def repeat3(fn, n, x):
    if n == 1:
        return fn(x)
    else:
        return fn(repeat3(fn, n-1, x))

def repeat(fn, n):
    return functools.partial(repeat3, fn, n)
查看更多
登录 后发表回答