I'm trying to write a function in python that is like:
def repeated(f, n):
...
where f
is a function that takes one argument and n
is a positive integer.
For example if I defined square as:
def square(x):
return x * x
and I called
repeated(square, 2)(3)
this would square 3, 2 times.
That should do it:
def repeated(f, n):
def rfun(p):
return reduce(lambda x, _: f(x), xrange(n), p)
return rfun
def square(x):
print "square(%d)" % x
return x * x
print repeated(square, 5)(3)
output:
square(3)
square(9)
square(81)
square(6561)
square(43046721)
1853020188851841
or lambda
-less?
def repeated(f, n):
def rfun(p):
acc = p
for _ in xrange(n):
acc = f(acc)
return acc
return rfun
Using reduce
and lamba.
Build a tuple starting with your parameter, followed by all functions you want to call:
>>> path = "/a/b/c/d/e/f"
>>> reduce(lambda val,func: func(val), (path,) + (os.path.dirname,) * 3)
"/a/b/c"
Something like this?
def repeat(f, n):
if n==0:
return (lambda x: x)
return (lambda x: f (repeat(f, n-1)(x)))
There is an itertools recipe called repeatfunc
that performs this operation.
From itertools recipes:
def repeatfunc(func, times=None, *args):
"""Repeat calls to func with specified arguments.
Example: repeatfunc(random.random)
"""
if times is None:
return starmap(func, repeat(args))
return starmap(func, repeat(args, times))
I use a third-party library, more_itertools
, that conveniently implements these recipes (optional):
import more_itertools as mit
list(mit.repeatfunc(square, 2, 3))
# [9, 9]
I think you want function composition:
def compose(f, x, n):
if n == 0:
return x
return compose(f, f(x), n - 1)
def square(x):
return pow(x, 2)
y = compose(square, 3, 2)
print y
Here's a recipe using reduce
:
def power(f, p, myapply = lambda init, g:g(init)):
ff = (f,)*p # tuple of length p containing only f in each slot
return lambda x:reduce(myapply, ff, x)
def square(x):
return x * x
power(square, 2)(3)
#=> 81
I call this power
, because this is literally what the power function does, with composition replacing multiplication.
(f,)*p
creates a tuple of length p
filled with f
in every index. If you wanted to get fancy, you would use a generator to generate such a sequence (see itertools
) - but note it would have to be created inside the lambda.
myapply
is defined in the parameter list so that it is only created once.
Using reduce and itertools.repeat (as Marcin suggested):
from itertools import repeat
from functools import reduce # necessary for python3
def repeated(func, n):
def apply(x, f):
return f(x)
def ret(x):
return reduce(apply, repeat(func, n), x)
return ret
You can use it as follows:
>>> repeated(os.path.dirname, 3)('/a/b/c/d/e/f')
'/a/b/c'
>>> repeated(square, 5)(3)
1853020188851841
(after importing os
or defining square
respectively)
来源:https://stackoverflow.com/questions/7359828/how-to-repeat-a-function-n-times