这样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')
相同吗?如果不是为什么?
答案 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。
看起来如果您要尝试比较lambda
和partial
这不是一个公平的测试 - 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模块来说,这可能是个好例子!