How can I bind arguments to a Python method to store a nullary functor for later invocation? Similar to C++’s boost::bind.
For example:
def add(x, y):
return x + y
add_5 = magic_function(add, 5)
assert add_5(3) == 8
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
functools.partial returns a callable wrapping a function with some or all of the arguments frozen.
import sys
import functools
print_hello = functools.partial(sys.stdout.write, "Hello worldn")
print_hello()
Hello world
The above usage is equivalent to the following lambda.
print_hello = lambda *a, **kw: sys.stdout.write("Hello worldn", *a, **kw)
Method 2
I’m not overly familiar with boost::bind, but the partial function from functools may be a good start:
>>> 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
Method 3
If functools.partial is not available then it can be easily emulated:
>>> make_printer = lambda s: lambda: sys.stdout.write("%sn" % s)
>>> import sys
>>> print_hello = make_printer("hello")
>>> print_hello()
hello
Or
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
Method 4
lambdas allow you to create a new unnamed function with less arguments and call the function!
>>> 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
edit
https://docs.python.org/2/library/functools.html#functools.partial
if you are planning to use named argument binding in the function call this is also applicable:
>>> from functools import partial >>> barfoo = partial(foobar, x=10) >>> barfoo(y=5,z=6) 21
Please note that if you bind arguments from the left you need to call the arguments by name. If you bind from the right it works as expected.
>>> 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
Method 5
This would work, too:
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
Method 6
Functors can be defined this way in Python. They’re callable objects. The “binding” merely sets argument values.
class SomeFunctor( object ):
def __init__( self, arg1, arg2=None ):
self.arg1= arg1
self.arg2= arg2
def __call___( self, arg1=None, arg2=None ):
a1= arg1 or self.arg1
a2= arg2 or self.arg2
# do something
return
You can do things like
x= SomeFunctor( 3.456 ) x( arg2=123 ) y= SomeFunctor( 3.456, 123 ) y()
Method 7
The question asks generally about binding arguments, but all answers are about functions. In case you are wondering, partial also works with class constructors (i.e. using a class instead of a function as a first argument), which can be useful for factory classes. You can do it as follows:
from functools import partial
class Animal(object):
def __init__(self, weight, num_legs):
self.weight = weight
self.num_legs = num_legs
animal_class = partial(Animal, weight=12)
snake = animal_class(num_legs = 0)
print(snake.weight) # prints 12
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0