2011-09-09 93 views
4

我試圖用Python語言編寫的函數是這樣的:如何重複功能n次

def repeated(f, n): 
    ... 

其中f是一個函數,它接受一個參數,n是一個正整數。

例如,如果我定義平方爲:

def square(x): 
    return x * x 

和我稱爲

repeated(square, 2)(3) 

這將方3,2次。

+2

哪裏是你的問題? –

回答

1

是這樣的?

def repeat(f, n): 
    if n==0: 
      return (lambda x: x) 
    return (lambda x: f (repeat(f, n-1)(x))) 
+1

這將導致堆棧溢出蟒蛇...... –

+1

它可能會,但我認爲它顯示了OP想要構建什麼。 – phimuemue

+1

這是真的:-) –

20

應該這樣做:

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稀少?

def repeated(f, n): 
    def rfun(p): 
     acc = p 
     for _ in xrange(n): 
      acc = f(acc) 
     return acc 
    return rfun 
+5

用於無lambda版本的+1。 – phimuemue

0

我想你想要的功能組成:

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 
+0

請注意OP是要求更高階的函數。您已經創建了一個重複應用相同函數的遞歸函數。不完全相同。 – Marcin

0

下面是使用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) - 但注意它必須在lambda內部創建。

myapply在參數列表中定義,因此它只創建一次。

+0

對於大p來說,這具有顯式構造長度爲n的元組的缺點。 –

+0

@ UweKleine-König是的,這就是爲什麼5年前我提到使用itertools生成器作爲替代方案。 – Marcin

+0

啊對,不好意思,只看着代碼... –

6

使用reduce和蘭巴。 構建起與您的參數元組,其次是所有的功能你要撥打:

>>> path = "https://stackoverflow.com/a/b/c/d/e/f" 
>>> reduce(lambda val,func: func(val), (path,) + (os.path.dirname,) * 3) 
"https://stackoverflow.com/a/b/c" 
0

使用減少和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

有一個itertools配方repeatfunc執行此操作。

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

我使用第三方庫,more_itertools,它可以方便地實現這些食譜(可選):

import more_itertools as mit 

list(mit.repeatfunc(square, 2, 3)) 
# [9, 9]