我一直在使用Python,我设置了以下代码情形:
import timeit
setting = """
import functools
def f(a,b,c):
pass
g = functools.partial(f,c=3)
h = functools.partial(f,b=5,c=3)
i = functools.partial(f,a=4,b=5,c=3)
"""
print timeit.timeit('f(4,5,3)', setup = setting, number=100000)
print timeit.timeit('g(4,5)', setup = setting, number=100000)
print timeit.timeit('h(4)', setup = setting, number=100000)
print timeit.timeit('i()', setup = setting, number=100000)结果是我得到了以下结果:
f: 0.181384086609
g: 0.39066195488
h: 0.425783157349
i: 0.391901016235为什么对分部函数的调用花费的时间更长?分部函数只是将参数转发给原始函数,还是将静态参数映射到整个函数?另外,如果所有参数都是预定义的,Python中有没有一个函数可以返回填充的函数体,就像函数i一样?
发布于 2013-06-30 17:31:14
为什么对分部函数的调用花费的时间更长?
由于额外的函数调用,使用partial编写的代码花费的时间大约要长两倍。函数调用are expensive:
中的函数调用开销相对较高,特别是与内置函数的执行速度相比。
-
是分部函数,只是将参数转发给原始函数,还是将静态参数映射到整个函数?
据我所知--是的,它就是forwards the arguments to the original function。
-
还有,如果所有的参数都是预定义的,Python语言中有没有一个函数可以返回被填充的函数体,比如
i?
不,我不知道Python中有这样的内置函数。但我认为可以做你想做的事情,因为函数是可以复制和修改的对象。
这是一个原型:
import timeit
import types
# http://stackoverflow.com/questions/6527633/how-can-i-make-a-deepcopy-of-a-function-in-python
def copy_func(f, name=None):
return types.FunctionType(f.func_code, f.func_globals, name or f.func_name,
f.func_defaults, f.func_closure)
def f(a, b, c):
return a + b + c
i = copy_func(f, 'i')
i.func_defaults = (4, 5, 3)
print timeit.timeit('f(4,5,3)', setup = 'from __main__ import f', number=100000)
print timeit.timeit('i()', setup = 'from __main__ import i', number=100000)这就给出了:
0.0257439613342
0.0221881866455发布于 2018-05-06 15:37:07
使用部分应用的参数调用函数的开销更大,因为函数调用的数量是原来的两倍。functools.partial()的效果与下面的示例类似:
def apply_one_of_two(f, a):
def g(b):
return f(a, b)
return g这意味着apply_one_of_two()返回一个函数,当它被调用时,这会导致对原始函数f的额外调用。
由于Python通常不会对此进行优化,因此它直接转化为额外的运行时工作。
但这并不是您的微基准测试中要考虑的唯一因素。您还可以在部分调用中从位置参数切换到关键字参数,这会带来额外的开销。
当您颠倒原始函数中的参数顺序时,您不需要在部分调用中使用关键字参数,然后运行时差异会有所减小,例如:
import timeit
setting = """
import functools
def f(a,b,c):
pass
g = functools.partial(f, 4)
h = functools.partial(f, 4, 5)
i = functools.partial(f, 4, 5, 3)
"""
print(timeit.timeit('f(4, 5, 3)', setup = setting, number=100000))
print(timeit.timeit('g(5, 3)', setup = setting, number=100000))
print(timeit.timeit('h(3)', setup = setting, number=100000))
print(timeit.timeit('i()', setup = setting, number=100000))输出(在Fedora 27/Python3.6下的英特尔Skylake i7上):
0.010069019044749439
0.01681053702486679
0.018060395028442144
0.011366961000021547https://stackoverflow.com/questions/17388438
复制相似问题