注意: 我想问的是是否有一种 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
''')
