Skip to main content
 首页 » 编程设计

Python之使用 'partial' 解决不适合 lambda 的后期绑定(bind)问题之成本与 yield

2025年05月04日11webabcd

注意: 我想问的是是否有一种 Pythonic 方式可以做到这一点(使用默认 args 似乎比使用 partial 更少 Pythonic)以及这两种方法是否有重大限制(“成本”- 我预计时间不会有显着差异,但也许还有其他限制,我没有看到会导致天平倾向于一种方法而不是另一种方法)。

我试图了解在 lambda 不可行的后期绑定(bind)情况下使用“部分”的成本。我创建了一些示例代码 based on this guide举例说明这一点。

由于延迟绑定(bind),以下内容无法按预期工作:

def create_thingies(): 
    thingies = [] 
    for i in range(1,6): 
        def thingy(x): 
            print("Some output", i) 
            return i ** (x * i) 
        thingies.append(thingy) 
    return thingies 
 
results=[] 
for thingy in create_thingies(): 
    results.append(thingy(2)) 
print(results) 

输出:

Some output 5 
Some output 5 
Some output 5 
Some output 5 
Some output 5 
[9765625, 9765625, 9765625, 9765625, 9765625] 

使用“部分”我们避免了这个问题,但代价是什么?

from functools import partial 
def create_thingies(): 
    thingies = [] 
    for i in range(1,6): 
        def thingy(i, x): 
            print("Some output", i) 
            return i ** (x * i) 
        thingies.append(partial(thingy, i)) 
    return thingies 
 
results=[] 
for thingy in create_thingies(): 
    results.append(thingy(2)) 
print(results) 

输出:

Some output 1 
Some output 2 
Some output 3 
Some output 4 
Some output 5 
[1, 16, 729, 65536, 9765625] 

我在这里看到了很多关于 lambda 与 partial 的讨论,但是在 lambda 不能很好地工作(一个非常复杂的函数)的情况下(如果函数有多个表达式)是 partial 的方式或者是否有更好的方法来将其强制转换为 lambda 表达式?

请您参考如下方法:

使用partial,不需要为i的每个值定义一次thingy,因为thingy不使用任何自由/全局变量,仅使用其参数。

from functools import partial 
 
def thingy(i, x): 
    print("Some output", i) 
    return i ** (x * i) 
 
thingies = [partial(thingy, i) for i in range(1,6)] 
results = [th(2) for th in thingies] 
print(results) 

至于成本,您应该分析一下性能是否可以接受。


这是一个比较 3 个选项的快速测试:

import timeit 
 
# The fastest: define a function using a default parameter value 
print timeit.timeit('results = [ th(2) for th in create_thingies()]', ''' 
def create_thingies(): 
    thingies = [] 
    for i in range(1,6): 
        def thingy(x,i=i): 
            #print("Some output", i) 
            return i ** (x * i) 
        thingies.append(thingy) 
    return thingies 
''') 
 
# The slowest, but IMO the easiest to read. 
print timeit.timeit('results = [ th(2) for th in create_thingies()]', ''' 
def create_thingies(): 
    from functools import partial 
    def thingy(i,x): 
        #print("Some output", i) 
        return i ** (x * i) 
    return [partial(thingy, i) for i in range(1,6)] 
''') 
 
# Only a little slower than the first 
print timeit.timeit('results = [ th(2) for th in create_thingies()]', ''' 
def create_thingies(): 
    def make_thingy(i): 
        def thingy(x): 
            #print("Some output", i) 
            return i ** (x * i) 
        return thingy 
    thingies = [make_thingy(i) for i in range(1,6)] 
    return thingies 
''')