how can I bind arguments to a python method to store a nullary functor for later invocation? similar to C++'s boost::bind
+12
A:
functools.partial
returns a callable based on a function with some or all of the arguments frozen.
~ $ python3.0
Python 3.0rc1 (r30rc1:66511, Sep 19 2008, 00:39:17)
Type "help", "copyright", "credits" or "license" for more information.
>>> import functools
>>> print_hello = functools.partial(print, "hello, world")
>>> print_hello()
hello, world
>>> print_hello("how are you?")
hello, world how are you?
>>>
(I use Py3k in the example so that I can freeze the print function, since it seems like the simplest example. functools.partial
has been available since 2.5.)
Jeremy Banks
2008-11-10 14:06:47
+5
A:
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
Matthew Trevor
2008-11-10 14:07:14
thanks. marked the top guy since he got it first.
Dustin Getz
2008-11-10 14:32:26
A:
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()
S.Lott
2008-11-10 14:57:19
interesting pattern, lots of boilerplate for trivial functions though.
Dustin Getz
2008-11-10 15:02:48
You can cut it down to something considerably simpler, depending on your actual use cases. The original question provides no guidance on how the binding occurs. Without specifics, there are too many bases to cover.
S.Lott
2008-11-10 15:11:59
+4
A:
If functools.partial
is not available then it can be easily emulated:
>>> make_printer = lambda s: lambda: sys.stdout.write("%s\n" % 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
J.F. Sebastian
2008-11-10 15:50:43
A:
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
Claudiu
2008-11-11 03:03:27