检查这个python代码:
from functools import partial
def summer(x, y):
return x+y
>>>partial(summer, 1, 2)
<functools.partial object at 0x10e648628>
但是,当我通过部分时间时:
import timeit
min(timeit.repeat(partial(summer, 1, 2)))
它似乎用 x=1 和 y=2 来评估夏天。
我明白发生了什么吗?我用时间对吗?当我为每个参数传递值时,我如何部分评估夏天?
编辑:为了清楚起见,我添加了以下评论作为此问题的一部分。
我的问题是部分(夏季,1,2)不评估夏季。那么,为什么在timeit.repeat中调用它来评估夏天呢?
在 Python 中,function
对象是"一等"对象。它们可以作为参数传递给函数,就像任何其他对象一样。在这种情况下, timeit.repeat
传递函数对象partial(summer, 1, 2)
,以便稍后可以在repeat
内部调用和计时函数对象。
partial(summer, 1, 2)
本身是将函数(summer
)作为参数传递给另一个函数(partial
)的另一个例子。你想要传递函数对象是有道理的,因为你还不想调用summer
。相反,您希望 partial
返回的函数对象有权访问summer
以便稍后在调用该函数对象时可以调用它。
partial(summer, 1, 2)
返回一个函数对象:
In [36]: partial(summer, 1, 2)
Out[36]: <functools.partial at 0x7ff31f0bd3c0>
如您所知,要调用该函数,您需要在函数后放置括号:
In [37]: partial(summer, 1, 2)()
Out[37]: 3
通常,当我使用timeit
时,我会将语句stmt
和设置作为字符串传递给timeit
函数:
In [41]: func = partial(summer, 1, 2)
In [42]: timeit.repeat('func()', 'from __main__ import func')
Out[42]: [0.11481308937072754, 0.10448503494262695, 0.1048579216003418]
但是,您是正确的,也可以传递可调用对象(例如函数对象)作为第一个参数:
timeit.repeat(func)
repeat
将调用func
并计时结果。您可以通过使用调试器单步执行代码来了解repeat
如何处理这种情况,如下所示pdb
:
import pdb
pdb.set_trace()
timeit.repeat(func)
在第 140 行周围的timeit.py
代码中,您将看到:
elif callable(stmt):
self.src = None
if isinstance(setup, str):
_setup = setup
def setup():
exec(_setup, global_ns, local_ns)
检查是否stmt
,第一个参数是可调用的。如果是,则func
设置为 stmt
,稍后调用func
(源代码)。
def inner(_it, _timer, _func=func):
setup()
_t0 = _timer()
for _i in _it:
_func() # <--- The function call happens here
_t1 = _timer()
return _t1 - _t0
return inner