2024-05-15 17:48:35 发布
网友
我的印象是下面的代码模式不好
new_data = map(lambda x: f(x, 30), data)
因为lambda函数需要创建len(data)次,因此效率很低。在这种情况下,下面的解决方法有用吗?
len(data)
g = lambda x: f(x, 30) new_data = map(g, data)
另外,如果给定的数据很大,用partial替换lambda函数是否有助于提高速度?
partial
Lambda只在map调用时创建一次
map
In [20]: l = list(range(100000)) In [21]: %timeit list(map(lambda x: x * 2, l)) 100 loops, best of 3: 13.8 ms per loop In [22]: g = lambda x: x * 2 In [23]: %timeit list(map(g, l)) 100 loops, best of 3: 13.8 ms per loop
如您所见,执行时间没有改变。
because the lambda function needs to be created len(data) times, thus inefficient.
不是这样,在本例中,lambda定义在编译时只计算一次,而不是len(data)次-出于性能原因,不需要将其分配给名称。看看谢尔盖的回答,他证明兰达在这个案子上一点都不贵。
如果为了清楚起见,您确实想给它命名,那么应该改用def语句。将lambda赋给名称被认为是错误的样式:根据PEP-8 Programming Recommendations,应该“始终使用def语句,而不是将lambda表达式直接绑定到标识符的赋值语句”。引用官方风格指南:
Yes:
def f(x): return 2*x
No:
f = lambda x: 2*x:
lambda和单行def之间的唯一区别是def将为其命名(可能是额外的加载常量):
def
>>> import dis >>> def _(x): return f(x, 30) >>> dis.dis(_) 2 0 LOAD_GLOBAL 0 (f) 2 LOAD_FAST 0 (x) 4 LOAD_CONST 1 (30) 6 CALL_FUNCTION 2 8 RETURN_VALUE >>> dis.dis(lambda x: f(x, 30)) 1 0 LOAD_GLOBAL 0 (f) 2 LOAD_FAST 0 (x) 4 LOAD_CONST 1 (30) 6 CALL_FUNCTION 2 8 RETURN_VALUE
正如您在上面看到的,两个表单编译成相同的字节码。
受lisp启发的函数map、filter和reduce在Python中总是感觉有点陌生。自从引入列表理解(2.0iim版)以来,它们就成了达到同样效果的惯用方法。所以这个:
filter
reduce
通常写为:
new_data = [f(x, 30) for x in data]
如果数据很大,而您只是在对其进行迭代,则生成器表达式将内存交换为cpu:
for value in (f(x, 30) for x in data): do_something_with(value)
像map、filter和reduce这样的lispy结构可能会失效(移到functools模块),我建议在新代码中使用列表理解和生成器表达式。
functools
最后,Python在性能方面出人意料地违反直觉。你应该经常进行侧写,以便检查你对绩效的信念。
底线:不要担心“优化”一个该死的东西,除非你已经分析了它并确定它是一个相关的瓶颈。
Lambda只在
map
调用时创建一次如您所见,执行时间没有改变。
不是这样,在本例中,lambda定义在编译时只计算一次,而不是
len(data)
次-出于性能原因,不需要将其分配给名称。看看谢尔盖的回答,他证明兰达在这个案子上一点都不贵。如果为了清楚起见,您确实想给它命名,那么应该改用def语句。将lambda赋给名称被认为是错误的样式:根据PEP-8 Programming Recommendations,应该“始终使用def语句,而不是将lambda表达式直接绑定到标识符的赋值语句”。引用官方风格指南:
lambda和单行
def
之间的唯一区别是def
将为其命名(可能是额外的加载常量):正如您在上面看到的,两个表单编译成相同的字节码。
受lisp启发的函数
map
、filter
和reduce
在Python中总是感觉有点陌生。自从引入列表理解(2.0iim版)以来,它们就成了达到同样效果的惯用方法。所以这个:通常写为:
如果数据很大,而您只是在对其进行迭代,则生成器表达式将内存交换为cpu:
像
map
、filter
和reduce
这样的lispy结构可能会失效(移到functools
模块),我建议在新代码中使用列表理解和生成器表达式。最后,Python在性能方面出人意料地违反直觉。你应该经常进行侧写,以便检查你对绩效的信念。
底线:不要担心“优化”一个该死的东西,除非你已经分析了它并确定它是一个相关的瓶颈。
相关问题 更多 >
编程相关推荐