1

也可以这样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')

等价?如果不是为什么?

4

1 回答 1

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()")

出去

$ 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。

看起来如果您正在尝试比较lambda并且partial这不是一个公平的测试 -par2因为它不调用所以少了一个调用lower,而par确实调用了。

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

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

... 所以par2只是一个lambda包含一个的,startswithpar一个包含两个lowerstartswith调用的部分。

因此它们不等效,par因此速度较慢。

为什么?

问题是“为什么f.lower().startswith不内联 - 是什么禁止语言内联它?”

首先,这个 Python 本身并不禁止这种内联——它是不同的 Python 实现做出决定,在我上面的测试中,它是 cpython 3。

其次,partial' 的工作不是内联函数,它只是......

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

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

如果您找不到任何可以执行您正在寻找的内联的东西,那么也许这是一个新的 Python 模块的好案例!

于 2015-10-17T16:43:22.453 回答