我想在Python 3.5中使用timeit来测量两个函数.第一个依赖于导入数学,第二个依赖于数学导入log2.我虽然可以通过在调用timeit.repeat时将适当的import语句作为设置字符串传递来处理此问题.但是我得到NameError:未定义名称“ math”.
我不想将函数作为它们的名称字符串传递.当函数不依赖于导入时,此代码在这里有效,但我需要用math.log2调用
期待您的回答.
def spam_log_v1():
for _ in range(1000):
math.log2(2)
def spam_log_v2():
for _ in range(1000):
log2(2)
if __name__ == '__main__':
import timeit
repeat = 3
number = 1000
unit = "usec"
unittosec = {"usec": 1e6, "msec": 1000, "sec": 1}
tests = [(spam_log_v1, 'import math'),
(spam_log_v2, 'from math import log2')]
for fct, setup in tests:
res = timeit.repeat(fct, setup=setup, repeat=repeat, number=number)
print("%s: %d loops, best of %d: %.3g %s per loop" %
(fct.__name__, number, repeat,
min(res) / number * unittosec[unit], unit))
解决方法:
由timeit.repeat运行的The inner
function看起来像这样:
def inner(_it, _timer{init}):
{setup}
_t0 = _timer()
for _i in _it:
{stmt}
_t1 = _timer()
return _t1 - _t0
其中{setup}替换为设置字符串,{stmt}替换为语句字符串.请注意,安装程序是从内部内部运行的.因此,如果在安装程序中放置导入语句,则模块名称将成为inner的局部变量.稍后,当从stmt调用spam_log_v1时,spam_log_v1无法使用该模块名称,因为该模块名称不在全局范围内.
解决方法是仅在脚本的全局级别导入数学和/或从数学导入log2.
import math
from math import log2
def spam_log_v1():
for _ in range(1000):
math.log2(2)
def spam_log_v2():
for _ in range(1000):
log2(2)
if __name__ == '__main__':
import timeit
repeat = 3
number = 1000
unit = "usec"
unittosec = {"usec": 1e6, "msec": 1000, "sec": 1}
tests = [
(spam_log_v1, ''),
(spam_log_v2, '')]
for fct, setup in tests:
res = timeit.repeat(fct, setup=setup, repeat=repeat, number=number)
print("%s: %d loops, best of %d: %.3g %s per loop" %
(fct.__name__, number, repeat,
min(res) / number * unittosec[unit], unit))