Reputation: 7404
Suppose I have function, f
, which takes in some variable and returns a variable of the same type. For simplicity, let's say
def f(x):
return x/2+1
I'm interested in applying f
to itself over and over. Something like f(f(f(...(f(x))...)))
.
I could do this like
s = f(x)
for i in range(100):
s = f(s)
But I was wondering if there was a simpler, less verbose way to doing the same thing. I wan't to avoid for
loops (just as a challenge to myself). Is there maybe some way of using map
or a similar function to accomplish this?
Upvotes: 9
Views: 1064
Reputation: 98485
You could factor out recursion:
from functools import partial
recurse = partial(lambda g,f,x,n: g(g,f,x,n), # capture g
lambda g,f,x,n: n and g(g, f, f(x), n-1) or x)
If you're into something better than a one-liner, recursion can be abolished:
import itertools
def recurse(f, x, n):
for _ in itertools.repeat(None, n):
x = f(x)
return x
Then:
>>> f = lambda x: x/2+1
>>> recurse(f, 42, 5)
7.0
>>> f(f(f(42)))
7.0
Upvotes: 0
Reputation: 361967
Is there maybe some way of using
map
or a similar function to accomplish this?
Not map
, but reduce
. I wouldn't use it for this, but you could call reduce
on an n-item sequence to cause f
to be called n times. For example:
>>> def f(x):
... return x+1
...
>>> reduce(lambda n,_: f(n), range(100), 42)
142
Explanation:
n
is assigned each successive return value of f
._
is the list of numbers from range(100)
. These numbers are all ignored. All that matters is how many there are.42
is the starting value.100
nested calls to f(f(f...(f(42))...))
results in 142
.
Upvotes: 8
Reputation: 177715
In Python, a for loop is the most ergonomic and readable way to do this. So I would consider this mostly an exercise — these are more natural to use in functional languages.
functools.reduce
collapses a list of values to a single value by repeatedly calling a function of two arguments. Here's factorial:
>>> import functools, operator
>>> operator.mul(2,3)
6
>>> functools.reduce(operator.mul, range(1, 10), 1)
362880
We can abuse this to use a list of values for its length only and ignore the actual contents.
>>> def f(x):
... return x/2+1
...
>>> functools.reduce(lambda x, y: f(x), range(10), 1)
1.9990234375
Or we can string together n copies of the (unary) function in a list and collapse them by applying each one to the accumulated value.
>>> import itertools
>>> functools.reduce(lambda x, g: g(x), itertools.repeat(f, 10), 1)
1.9990234375
Upvotes: 5
Reputation: 45339
The construct would be recursion. But recursion requires that your call stack ends at some point. Such a case could work with an algorithm such as:
if(x == 0):
return 1
# this will make sure it ends at the preceding line in the next call
return f(x - 1)
This is typically the approach used to compute results such as the factorial.
To use an example, adding a requirement (that you only compute if x < 2, just as an example):
def f(x):
if(x < 2):
return 1
return f(x/2+1)
The key is that there be a point at which the call stack starts returning (to avoid an overflow)
Upvotes: 1
Reputation: 71461
While it is not clear from your example if you are trying to calculate a final numerical result or accumulate a list of values, you can use a very simple recursive approach with a lambda function:
Single value:
f = lambda x, c = 1:x if c == 100 else f(x/2 + 1, c+1)
>>f(200)
2
List of values:
f = lambda x, c = 1:x if c == 100 else f(x+[x[-1]/2+1], c+1)
>>f([200])
[200, 101, 51, 26, 14, 8, 5, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
Upvotes: 2
Reputation: 46
What I think you're asking about is concept called Recursion. You could use something like a lambda function but recursive calls in a for loop aren't inherently bad. I'd go read more about recursive functions in general and then look for python implementations specifically.
Upvotes: -1
Reputation: 915
You could add the function itself in the return line of the definition. An example would be the top answer here How can I build a recursive function in python?
Upvotes: 0