python将lambda函数映射到lis

2024-05-15 17:48:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我的印象是下面的代码模式不好

new_data = map(lambda x: f(x, 30), data)

因为lambda函数需要创建len(data)次,因此效率很低。在这种情况下,下面的解决方法有用吗?

g = lambda x: f(x, 30)
new_data = map(g, data)

另外,如果给定的数据很大,用partial替换lambda函数是否有助于提高速度?


Tags: 数据方法lambda函数代码mapnewdata
2条回答

Lambda只在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将为其命名(可能是额外的加载常量):

>>> 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启发的函数mapfilterreduce在Python中总是感觉有点陌生。自从引入列表理解(2.0iim版)以来,它们就成了达到同样效果的惯用方法。所以这个:

new_data = map(lambda x: f(x, 30), data)

通常写为:

new_data = [f(x, 30) for x in data]

如果数据很大,而您只是在对其进行迭代,则生成器表达式将内存交换为cpu:

for value in (f(x, 30) for x in data):
    do_something_with(value)

mapfilterreduce这样的lispy结构可能会失效(移到functools模块),我建议在新代码中使用列表理解和生成器表达式。

最后,Python在性能方面出人意料地违反直觉。你应该经常进行侧写,以便检查你对绩效的信念。

底线:不要担心“优化”一个该死的东西,除非你已经分析了它并确定它是一个相关的瓶颈。

相关问题 更多 >