88 Stimmen

Python Argument Binder

Wie kann ich Argumente an eine Python-Methode binden, um einen nullären Funktor zur späteren Ausführung zu speichern? Ähnlich wie bei boost::bind in C++.

Zum Beispiel:

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

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

98voto

Jeremy Punkte 1

functools.partial gibt einen Aufruf zurück, der eine Funktion mit einigen oder allen Argumenten einfriert.

import sys
import functools

print_hello = functools.partial(sys.stdout.write, "Hallo Welt\n")

print_hello()

Hallo Welt

Die obige Verwendung ist äquivalent zu folgendem lambda.

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

85voto

Matthew Trevor Punkte 13396

Ich bin nicht besonders vertraut mit boost::bind, aber die partial-Funktion aus functools könnte ein guter Anfang sein:

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

15voto

jfs Punkte 370717

Wenn functools.partial nicht verfügbar ist, kann es einfach emuliert werden:

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

Alternatively

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

14voto

Alexander Oh Punkte 22027

Lambdas ermöglichen es Ihnen, eine neue unbenannte Funktion mit weniger Argumenten zu erstellen und die Funktion aufzurufen!

>>> def foobar(x,y,z):
...     print "%d, %d, %d" % (x,y,z)
>>> foobar(1,2,3) # rufe normale Funktion auf

>>> bind = lambda x: foobar(x, 10, 20) # binde 10 und 20 an foobar
>>> bind(1) # gib 1, 10, 20 aus

>>> bind = lambda: foobar(1,2,3) # binde alle Elemente  
>>> bind()  # gib 1, 2, 3 aus

bearbeiten

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

Wenn Sie vorhaben, benannte Argumente an den Funktionsaufruf zu binden, ist dies ebenfalls anwendbar:

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

Bitte beachten Sie, dass Sie, wenn Sie Argumente von links binden, die Argumente nach Namen aufrufen müssen. Wenn Sie von rechts binden, funktioniert es wie erwartet.

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

8voto

Claudiu Punkte 215027

Dies würde auch funktionieren:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X