python的部分内联调用吗?

时间:2015-10-17 11:38:06

标签: python python-2.7 inline functools

这样par

path = u'/a/b/c'
lam = lambda f: f.lower().startswith(u'distantlod')
par = functools.partial(lam, path)

par

path = u'/a/b/c'
startsWith = path.lower().startswith
par = lambda: startsWith(u'distantlod')

相同吗?如果不是为什么?

1 个答案:

答案 0 :(得分:0)

这是我使用cProfile进行的实验,看看我是否可以确认@ yuvi的测量结果。

代码par_profile.py

import cProfile as profile
import functools


path = u'/a/b/c'

lam = lambda f: f.lower().startswith(u'distantlod')
par = functools.partial(lam, path)

startsWith = path.lower().startswith
par2 = lambda: startsWith(u'distantlod')


if __name__ == '__main__':
    profile.run("for _ in range(1000000): par()")
    profile.run("for _ in range(1000000): par2()")

<强> OUT

$ python par_profile.py 
         3000003 function calls in 0.536 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.148    0.148    0.536    0.536 <string>:1(<module>)
  1000000    0.242    0.000    0.388    0.000 par_profile.py:7(<lambda>)
        1    0.000    0.000    0.536    0.536 {built-in method exec}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
  1000000    0.054    0.000    0.054    0.000 {method 'lower' of 'str' objects}
  1000000    0.092    0.000    0.092    0.000 {method 'startswith' of 'str' objects}


         2000003 function calls in 0.347 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.130    0.130    0.347    0.347 <string>:1(<module>)
  1000000    0.126    0.000    0.218    0.000 par_profile.py:11(<lambda>)
        1    0.000    0.000    0.347    0.347 {built-in method exec}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
  1000000    0.092    0.000    0.092    0.000 {method 'startswith' of 'str' objects}

首先,我的机器上的这些测量结果与@ yuvi的数字相符:

  • par约为540纳秒
  • par2约为350纳秒

所以我同意par2看起来更快200 ns。

看起来如果您要尝试比较lambdapartial这不是一个公平的测试 - par2只有少一个电话,因为它没有&#39 ; t调用lower,而par调用。{/ p>

为了说明原因,startsWith可以改写为:

lower_path = path.lower()
startsWith = lower_path.startswith

...所以par2仅包含一个lambda startswith,而par是包含lower和{{1}的部分调用。

因此它们不相等,因此startswith速度较慢。

<强> WHY吗

问题是&#34;为什么par没有内联 - 什么禁止语言内联?&#34;

首先,这个Python本身并不禁止这种内联 - 它是做出决策的不同Python实现,在我的测试的情况下它是cpython 3。

其次,f.lower().startswith的工作不是内联函数,只是...

  

“冻结”函数参数和/或关键字的某些部分,从而产生带有简化签名的新对象(doc

相反,如果您正在查看将在Python中进行内联的内容,那么我可以查看Numba's jit之类的内容或使用PyPy进行一些实验(如果您发现某些内容,请回复此处有趣的改进)。

如果您无法找到任何可以进行内联寻找的内容,那么对于新的Python模块来说,这可能是个好例子!