如何在Python中绑定函数参数?

84 投票
7 回答
36777 浏览
提问于 2025-04-11 09:33

我怎么能把参数绑定到一个Python函数上,这样我以后可以在不传参数(或者只传少量额外参数)的情况下调用它呢?

举个例子:

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

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

这里我需要什么样的magic_function呢?


在使用框架和库的时候,人们常常会不小心在给回调函数传参数时立即调用了一个函数,比如说on_event(action(foo))。解决这个问题的方法是把foo作为参数绑定到action上,可以使用这里描述的一些技巧。比如可以参考如何在Tkinter中给按钮命令传递参数?在Python中使用字典作为开关语句

不过,有些API允许你单独传递要绑定的参数,并会为你完成绑定。特别是标准库中的线程API就是这样工作的。可以查看线程在调用Thread.start之前就开始运行。如果你想自己设置一个这样的API,可以参考我怎么能写一个简单的回调函数?

显式绑定参数也是避免在使用闭包时出现延迟绑定问题的一种方法。这个问题是指,比如在for循环或列表推导式中的lambda会产生多个函数,但它们计算的结果是一样的。可以查看lambda函数的闭包捕获了什么?在循环(或推导式)中创建函数(或lambda)

7 个回答

14

如果 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
79

使用 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
95

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)

撰写回答