【问题标题】:lambda is slower than function call in python, whylambda 比 python 中的函数调用慢,为什么
【发布时间】:2014-12-19 21:02:01
【问题描述】:

我觉得lambda比函数调用快,但是经过测试,我发现我错了。函数调用肯定比 lambda 调用快。

谁能告诉我为什么?

以及如何加快Python中的函数调用?

我使用的是 Ubuntu 14.04 和 Python 2.7.6

>>> timeit('def a():return 222*333 ;a()')
0.08195090293884277
>>> timeit('a=lambda:222*333 ;a()')
0.11071300506591797

>>> timeit('a=lambda: [].extend(range(10)) ;a()')
0.40241098403930664
>>> timeit('a=lambda: [].extend(range(10)) ;a()')
0.4011270999908447
>>> timeit('a=lambda: [].extend(range(10)) ;a()')
0.4064619541168213
>>> timeit('def a(): return [].extend(range(10)) ;a()')
0.07965493202209473
>>> timeit('def a(): return [].extend(range(10)) ;a()')
0.08039593696594238
>>> timeit('def a(): return [].extend(range(10)) ;a()')
0.08103609085083008
>>> timeit('def a(): return [].extend(range(10)) ;a()')
0.08639097213745117

对不起我的错误,没有区别。正确测试:

>>> timeit('a()', setup="def a():return 222*333")
0.07061290740966797
>>> timeit('a()', setup="a=lambda: 222*333")
0.06967616081237793

【问题讨论】:

    标签: python function lambda


    【解决方案1】:

    timeit('def a(): return [].extend(range(10)) ;a()') 没有调用a();对a() 的调用是a 定义的一部分:

    In [34]: def a(): return [].extend(range(10)) ;a()
    
    In [35]: import dis
    
    In [36]: dis.dis(a)
      1           0 BUILD_LIST               0
                  3 LOAD_ATTR                0 (extend)
                  6 LOAD_GLOBAL              1 (range)
                  9 LOAD_CONST               1 (10)
                 12 CALL_FUNCTION            1
                 15 CALL_FUNCTION            1
                 18 RETURN_VALUE        
                 19 LOAD_GLOBAL              2 (a)
                 22 CALL_FUNCTION            0       #<-- a is called
                 25 POP_TOP             
    

    如果单独测试,差异可以忽略不计:

    In [24]: %timeit a=lambda: [].extend(range(10))
    10000000 loops, best of 3: 68.6 ns per loop
    
    In [25]: %timeit def a2(): return [].extend(range(10))
    10000000 loops, best of 3: 68.8 ns per loop
    
    In [22]: %timeit a()
    1000000 loops, best of 3: 445 ns per loop
    
    In [23]: %timeit a2()
    1000000 loops, best of 3: 442 ns per loop
    

    【讨论】:

    • 对不起我的愚蠢错误...我运行了这个测试,没有绝对的区别。 &gt;&gt;&gt; timeit('a()', setup="def a():return 222*333") 0.07061290740966797 &gt;&gt;&gt; timeit('a()', setup="a=lambda: 222*333") 0.06967616081237793
    【解决方案2】:

    如上所述,您的第一个测试仅描述定义 a 所需的时间。它实际上从未被调用过。

    Lambda 表达式和“普通”函数生成完全相同的字节码,如您使用 dis 模块所见:

    def a(): return 10
    b = lambda: 10
    
    import dis
    
    >>> dis.dis(a)
    1           0 LOAD_CONST               1 (10)
                3 RETURN_VALUE
    >>> dis.dis(b)
    1           0 LOAD_CONST               1 (10)
                3 RETURN_VALUE
    

    【讨论】:

    • 这是很重要的一点。人们有时认为“lambda 函数”是一种特殊的东西,但事实并非如此:lambda 只是一个用于制作普通旧函数的关键字,主要是因为它可以内联使用。而已。他们没有魔法。
    • @DSM 实际上 lambdas 等效于包含单个 return 语句的函数的更受限制的情况。所以编译一个 lambda 可能比编译一个函数要简单一些。
    • @augurar:这是我第一次听到有人建议 lambdas(或 Python 中的任何语法选择,真的)的优点是更简单的编译。无论如何,重点不是 lambda 可以用来创建任何函数,而是 lambda 关键字创建的一个函数,而不是“lambda 函数”。
    【解决方案3】:

    调用 lambda 与调用函数没有区别。 lambda 只是一个使用单个表达式创建的函数,没有名称。

    假设我们有两个相同的函数,一个使用函数定义创建,另一个使用 lambda 表达式:

    def a():
        return 222*333
    
    b = lambda: 222*333
    

    我们看到两者都是相同类型的函数对象,并且它们都共享等效的字节码:

    >>> type(a)
    <class 'function'>
    >>> type(b)
    <class 'function'>
    
    >>> import dis
    >>> dis.dis(a)
      2           0 LOAD_CONST               3 (73926)
                  2 RETURN_VALUE
    >>> dis.dis(b)
      1           0 LOAD_CONST               3 (73926)
                  2 RETURN_VALUE
    

    如何加快速度?你没有。是蟒蛇。它为您预先优化。您无需再处理此代码。

    也许你可以把它交给另一个解释器,或者用另一种语言重写它,但如果你坚持使用 Python,现在就没有什么可做的了。

    定时

    这是我检查时间的方法。

    Timeit 的 timeitrepeat 都可以调用:

    import timeit
    

    请注意,timeit.repeat 也接受 repeat 参数:

    >>> min(timeit.repeat(a, repeat=100))
    0.06456905393861234
    >>> min(timeit.repeat(b, repeat=100))
    0.06374448095448315
    

    这些差异太小,不显着。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-01
      • 2021-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多