use*_*310 18 python function partial functools
我一直在使用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)
Run Code Online (Sandbox Code Playgroud)
我得到以下结果:
f: 0.181384086609
g: 0.39066195488
h: 0.425783157349
i: 0.391901016235
Run Code Online (Sandbox Code Playgroud)
为什么对部分函数的调用需要更长时间?部分函数是将参数转发到原始函数还是映射静态参数?而且,在Python中是否有一个函数返回一个函数的主体,假定所有参数都是预定义的,就像函数i一样?
war*_*iuc 18
为什么对部分函数的调用需要更长时间?
partial由于额外的函数调用,代码大约需要两倍的时间.函数调用很昂贵:
Python中的函数调用开销相对较高,特别是与内置函数的执行速度相比.
-
部分函数是将参数转发到原始函数还是映射静态参数?
据我所知 - 是的,它只是将参数转发给原始函数.
-
而且,在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)
Run Code Online (Sandbox Code Playgroud)
这使:
0.0257439613342
0.0221881866455
Run Code Online (Sandbox Code Playgroud)
使用部分应用的参数调用函数会更昂贵,因为函数调用的次数增加了一倍。的效果functools.partial()类似于这个例子:
def apply_one_of_two(f, a):
def g(b):
return f(a, b)
return g
Run Code Online (Sandbox Code Playgroud)
这意味着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))
Run Code Online (Sandbox Code Playgroud)
输出(在 Fedora 27/Python 3.6 下的 Intel Skylake i7 上):
0.010069019044749439
0.01681053702486679
0.018060395028442144
0.011366961000021547
Run Code Online (Sandbox Code Playgroud)