71 votes

Classeurs d'arguments en Python

Comment puis-je lier des arguments à une méthode Python afin de stocker un functor nullaire pour une invocation ultérieure ? Comme pour le C++ boost::bind .

Par exemple :

def add(x, y):
    return x + y

add_5 = magic_function(add, 5)
assert add_5(3) == 8

0 votes

J'ai enfin trouvé une version de cette question où les réponses acceptées et populaires sont toutes de l'ordre de functools.partial au lieu d'un hack de nested-lambda ou d'un abus de default-argument-binding. Dans les favoris.

86voto

Jeremy Banks Points 32470

functools.partial renvoie un appelable enveloppant une fonction avec certains ou tous les arguments figés.

import sys
import functools

print_hello = functools.partial(sys.stdout.write, "Hello world\n")

print_hello()

Hello world

L'usage ci-dessus est équivalent à ce qui suit lambda .

print_hello = lambda *a, **kw: sys.stdout.write("Hello world\n", *a, **kw)

1 votes

Pour python2.6 au moins, vous pouvez utiliser de futur Importation de la fonction print_function

67voto

Matthew Trevor Points 5277

Je ne suis pas très familier avec boost::bind, mais la fonction partial de la fonction functools peut être un bon début :

>>> from functools import partial

>>> def f(a, b):
...     return a+b

>>> p = partial(f, 1, 2)
>>> p()
3

>>> p2 = partial(f, 1)
>>> p2(7)
8

11 votes

Cet exemple est meilleur que la réponse acceptée, car il montre une liaison partielle.

0 votes

...bien que ce serait mieux si la fonction f lui-même n'a pas traité ses deux arguments de manière symétrique afin qu'il soit évident de savoir lequel des deux arguments est lié dans la liaison partielle (qui, je suppose, est le premier) - comme dans def f(a, b): return a + 2*b

12voto

J.F. Sebastian Points 102961

Si functools.partial n'est pas disponible, il peut être facilement émulé :

>>> make_printer = lambda s: lambda: sys.stdout.write("%s\n" % s)
>>> import sys
>>> print_hello = make_printer("hello")
>>> print_hello()
hello

Ou

def partial(func, *args, **kwargs):
    def f(*args_rest, **kwargs_rest):
        kw = kwargs.copy()
        kw.update(kwargs_rest)
        return func(*(args + args_rest), **kw) 
    return f

def f(a, b):
    return a + b

p = partial(f, 1, 2)
print p() # -> 3

p2 = partial(f, 1)
print p2(7) # -> 8

d = dict(a=2, b=3)
p3 = partial(f, **d)
print p3(), p3(a=3), p3() # -> 5 6 5

11voto

Alex Points 3973

Les lambdas vous permettent de créer une nouvelle fonction sans nom avec moins d'arguments et d'appeler la fonction !

>>> def foobar(x,y,z):
...     print "%d, %d, %d" % (x,y,z)
>>> foobar(1,2,3) # call normal function

>>> bind = lambda x: foobar(x, 10, 20) # bind 10 and 20 to foobar
>>> bind(1) # print 1, 10, 20

>>> bind = lambda: foobar(1,2,3) # bind all elements  
>>> bind()  # print 1, 2, 3

modifier

https://docs.python.org/2/library/functools.html#functools.partial

si vous envisagez d'utiliser la liaison d'arguments nommés dans l'appel de fonction, ceci est également applicable :

>>> from functools import partial
>>> barfoo = partial(foobar, x=10)
>>> barfoo(y=5,z=6)
21

Veuillez noter que si vous liez des arguments depuis la gauche, vous devez appeler les arguments par leur nom. Si vous liez les arguments par la droite, cela fonctionne comme prévu.

>>> barfoo(5,6) 
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foobar() got multiple values for keyword argument 'x'
>>> f = partial(foobar, z=20)
>>> f(1,1)
22

1 votes

Cela devrait être la réponse acceptée. C'est la façon Python de lier les arguments aux appelables.

7voto

Claudiu Points 58398

Cela fonctionnerait aussi :

def curry(func, *args):
    def curried(*innerargs):
       return func(*(args+innerargs))
    curried.__name__ = "%s(%s, ...)" % (func.__name__, ", ".join(map(str, args)))
    return curried

>>> w=curry(sys.stdout.write, "Hey there")
>>> w()
Hey there

0 votes

Ce n'est pas un curry. Le curry est pour les fonctions avec plusieurs arguments. Le curry fonctionne comme ceci : Étant donné g = curry(f) nous avons f(x1,x2,...) = g(x1)(x2)...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X