Как повторить функцию n раз - PullRequest
5 голосов
/ 09 сентября 2011

Я пытаюсь написать функцию в Python, которая выглядит так:

def repeated(f, n):
    ...

, где f - это функция, которая принимает один аргумент, а n - положительное целое число.

Например, если я определил квадрат как:

def square(x):
    return x * x

и я позвонил

repeated(square, 2)(3)

это будет квадрат 3, 2 раза.

Ответы [ 7 ]

22 голосов
/ 09 сентября 2011

Что должно сделать это:

 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)

вывод:

 square(3)
 square(9)
 square(81)
 square(6561)
 square(43046721)
 1853020188851841

или lambda -less?

def repeated(f, n):
    def rfun(p):
        acc = p
        for _ in xrange(n):
            acc = f(acc)
        return acc
    return rfun
9 голосов
/ 27 марта 2014

Использование reduce и ламба.Создайте кортеж, начиная с вашего параметра, за которым следуют все функции, которые вы хотите вызвать:

>>> path = "/a/b/c/d/e/f"
>>> reduce(lambda val,func: func(val), (path,) + (os.path.dirname,) * 3)
"/a/b/c"
2 голосов
/ 09 сентября 2011

Как то так?

def repeat(f, n):
     if n==0:
             return (lambda x: x)
     return (lambda x: f (repeat(f, n-1)(x)))
0 голосов
/ 26 августа 2017

Существует рецепт itertools под названием repeatfunc, который выполняет эту операцию.

Из рецептов itertools :

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))

Я использую стороннюю библиотеку, more_itertools, которая удобно реализует эти рецепты (необязательно):

import more_itertools as mit

list(mit.repeatfunc(square, 2, 3))
# [9, 9]
0 голосов
/ 22 мая 2014

С помощью Reduce и itertools.repeat (как предложил Марцин):

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

Вы можете использовать его следующим образом:

>>> repeated(os.path.dirname, 3)('/a/b/c/d/e/f')
'/a/b/c'

>>> repeated(square, 5)(3)
1853020188851841

(после импорта os или определения square соответственно)

0 голосов
/ 15 сентября 2012

Вот рецепт, использующий 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

Я называю это power, потому что это буквально то, что делает функция мощности, с композицией, заменяющей умножение.

(f,)*p создает кортеж длины p, заполненный f в каждом индексе.Если вы хотите получить фантазию, вы должны использовать генератор для генерации такой последовательности (см. itertools) - но обратите внимание, что она должна быть создана внутри лямбды.

myapply определяется в списке параметров, поэтому он создается только один раз.

0 голосов
/ 09 сентября 2011

Я думаю, вы хотите состав функции:

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
...