/ / Comment répéter une fonction n fois - python, fonctions d'ordre supérieur

Comment répéter une fonction n fois - python, fonctions d'ordre supérieur

J'essaie d'écrire une fonction en python qui ressemble à:

def repeated(f, n):
...

f est une fonction qui prend un argument et n est un entier positif.

Par exemple, si j'ai défini carré comme:

def square(x):
return x * x

et j'ai appelé

repeated(square, 2)(3)

cela équivaudrait 3, 2 fois.

Réponses:

20 pour la réponse № 1

Ça devrait le faire:

 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)

sortie:

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

ou lambda-Moins?

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

8 pour la réponse № 2

En utilisant reduce et lamba. Construisez un tuple à partir de votre paramètre, suivi de toutes les fonctions que vous souhaitez appeler:

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

2 pour la réponse № 3

Quelque chose comme ça?

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

0 pour la réponse № 4

Je pense que vous voulez une composition fonctionnelle:

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 pour la réponse № 5

Voici une recette utilisant 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

J'appelle ça power, parce que c’est littéralement ce que fait la fonction de pouvoir, la composition remplaçant la multiplication.

(f,)*p crée un tuple de longueur p rempli avec f dans tous les index. Si vous voulez avoir l’imagination, vous utiliseriez un générateur pour générer une telle séquence (voir itertools) - mais notez qu'il devrait être créé à l'intérieur du lambda.

myapply est défini dans la liste de paramètres de sorte qu'il ne soit créé qu'une seule fois.


0 pour la réponse № 6

Utilisation de reduction et de itertools.repeat (comme suggéré par Marcin):

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

Vous pouvez l'utiliser comme suit:

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

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

(après importation os ou définir square respectivement)


0 pour la réponse № 7

Il existe une recette itertools appelée repeatfunc qui effectue cette opération.

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

J'utilise une bibliothèque tierce, more_itertools, qui implémente commodément ces recettes (facultatif):

import more_itertools as mit

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