Python Argument Binders
如何将参数绑定到python方法以存储空函数以供以后调用?类似于C++的EDCOX1,0Ω。
例如:
1 2 3 4 5 | def add(x, y): return x + y add_5 = magic_function(add, 5) assert add_5(3) == 8 |
1 2 3 4 5 6 7 | import sys import functools print_hello = functools.partial(sys.stdout.write,"Hello world ") print_hello() |
1 | Hello world |
上述用法相当于以下
1 2 | print_hello = lambda *a, **kw: sys.stdout.write("Hello world ", *a, **kw) |
我不太熟悉boost::bind,但是来自
1 2 3 4 5 6 7 8 9 10 11 12 | >>> 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 |
如果
1 2 3 4 5 6 | >>> make_printer = lambda s: lambda: sys.stdout.write("%s " % s) >>> import sys >>> print_hello = make_printer("hello") >>> print_hello() hello |
或
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 |
lambda允许您用更少的参数创建一个新的未命名函数,并调用该函数!
1 2 3 4 5 6 7 8 9 | >>> 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
如果计划在函数调用中使用命名参数绑定,这也适用于:
1 2 3 4 | >>> from functools import partial >>> barfoo = partial(foobar, x=10) >>> barfoo(y=5,z=6) 21 |
尽管如此,请注意
1 2 3 4 5 6 7 | >>> 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 2 3 4 5 6 7 8 9 | 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 |
函数可以用这种方式在Python中定义。它们是可调用的对象。"binding"只设置参数值。
1 2 3 4 5 6 7 8 9 | 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 |
你可以做像
1 2 3 4 5 | x= SomeFunctor( 3.456 ) x( arg2=123 ) y= SomeFunctor( 3.456, 123 ) y() |