def thing(mode, data):
return [
item for item in data
if {
'large': lambda item: item > 100,
'small': lambda item: item < 100,
}[mode](item)
]
此列表推导生成lambda的字典,通过mode
参数检索一个lambda,并将其应用于当前正在处理的列表项。我的问题是:这有什么性能特征?
在listcomp的每次迭代期间是否从头开始创建整个字典?或者它是创建一次并用于每个项目?
答案 0 :(得分:3)
在listcomp的每次迭代中是否从头开始创建整个字典
是。
或是它被创建一次并用于每个项目?
没有
幸运的是,在这种情况下(以及我能想到的所有其他类似情况),提前构建字典很容易:
d = {
'large': lambda item: item > 100,
'small': lambda item: item < 100,
}
return [item for item in data if d[mode](item)]
甚至,
func = {
'large': lambda item: item > 100,
'small': lambda item: item < 100,
}[mode]
return [item for item in data if func(item)]
答案 1 :(得分:2)
我很确定这会导致整个字典从头开始为列表的每个元素创建。 python列表推导的基本语法如下,
[ E1 for ID in E2 if E3 ]
,
其中E1,E2和E3是表达式。当解释器开始评估列表理解时,E2被评估一次。对E2评估的集合的每个成员评估E1和E3。所以,是的。在你的问题中,每次都是从头开始构建字典,但你可以通过在列表理解之前声明字典来轻松解决这个问题。
答案 2 :(得分:1)
你的字典每个循环创建一次,使你的列表理解速度比你缓存字典的速度快两倍:
>>> %timeit thing1('small', [1, 2, 3, 4, 5, 6])
100000 loops, best of 3: 2.4 us per loop
>>> %timeit thing2('small', [1, 2, 3, 4, 5, 6])
1000000 loops, best of 3: 1.06 us per loop
thing1
是您原来的功能。 thing2
是:
d = {
'large': lambda item: item > 100,
'small': lambda item: item < 100,
}
def thing3(mode, data):
return list(filter(d[mode], data))
filter(f, data)
是item for item in data if f(item)
的简写。在Python 3中,它创建了一个迭代器,它只在迭代时过滤掉项目。