Python参数绑定器
如何将参数绑定到一个Python方法来存储一个nullary函子以供以后调用? 类似于C ++的boost::bind
。
functools.partial
返回一个可调用的封装函数,其中一些或全部参数被冻结。
import sys import functools print_hello = functools.partial(sys.stdout.write, "Hello world\n") print_hello()
Hello world
上面的用法相当于下面的lambda
。
print_hello = lambda *a, **kw: sys.stdout.write("Hello world\n", *a, **kw)
我不太熟悉boost :: bind,但functools
的partial
函数可能是一个好的开始:
>>> 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
如果functools.partial
不可用,那么可以很容易地模拟:
>>> make_printer = lambda s: lambda: sys.stdout.write("%s\n" % s) >>> import sys >>> print_hello = make_printer("hello") >>> print_hello() hello
要么
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
这也可以工作:
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
lambdas允许你用较less的参数创build一个新的匿名函数并调用函数!
>>> 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
编辑
https://docs.python.org/2/library/functools.html#functools.partial
如果您打算在函数调用中使用命名参数绑定,则也适用:
>>> from functools import partial >>> barfoo = partial(foobar, x=10) >>> barfoo(y=5,z=6) 21
请注意
>>> 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
函子可以用Python来定义。 他们是可调用的对象。 “绑定”只是设置参数值。
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
你可以做类似的事情
x= SomeFunctor( 3.456 ) x( arg2=123 ) y= SomeFunctor( 3.456, 123 ) y()