也可以这样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')
等价?如果不是为什么?
也可以这样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')
等价?如果不是为什么?
这是我对 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
包含一个的,startswith
而par
一个包含两个lower
和startswith
调用的部分。
因此它们不等效,par
因此速度较慢。
为什么?
问题是“为什么f.lower().startswith
不内联 - 是什么禁止语言内联它?”
首先,这个 Python 本身并不禁止这种内联——它是不同的 Python 实现做出决定,在我上面的测试中,它是 cpython 3。
其次,partial
' 的工作不是内联函数,它只是......
“冻结”函数参数和/或关键字的某些部分,从而生成具有简化签名 ( doc )的新对象
相反,如果您正在寻找可以在 Python 中进行内联的东西,那么我会查看Numba 的 jit 之类的东西或使用 PyPy 进行一些实验(如果您发现一些有趣的改进,请在此处回复)。
如果您找不到任何可以执行您正在寻找的内联的东西,那么也许这是一个新的 Python 模块的好案例!