Python Timeit和“全局名称未定义”
我在使用timing函数来优化代码时遇到了问题。例如,我在一个文件里写了一些带参数的函数,我们叫这个文件为 myfunctions.py
,里面包含了:
def func1(X):
Y = X+1
return Y
然后我在另一个文件 test.py
中测试这个函数,在这里我调用了计时器函数来测试代码的性能(当然是更复杂的问题!),这个文件包含了:
import myfunctions
X0 = 1
t = Timer("Y0 = myfunctions.func1(X0)")
print Y0
print t.timeit()
这里的 Y0
没有被计算出来,即使我把 print Y0
这一行注释掉,还是出现了错误 global name 'myfunctions' is not defined
。
如果我用以下命令来指定设置:
t = Timer("Y0 = myfunctions.func1(X0)","import myfunctions")
那么就出现了另一个错误 global name 'X0' is not defined
。
有没有人知道怎么解决这个问题?非常感谢。
2 个回答
你之所以看到Y0
是未定义的,是因为你在字符串里定义了它,但在执行的开始阶段,这个字符串还没有被计算出来,所以变量还没有被创建。为了让它在使用之前就被定义好,可以在脚本的开头加一句Y0 = 0
。
所有外部的函数和变量都必须通过Timer
的setup
参数来传递。所以你需要像这样写"import myfunctions; X0 = 1"
作为设置参数。
这样就可以正常工作了:
from timeit import Timer
import myfunctions
X0 = 1
Y0 = 0 #Have Y0 defined
t = Timer("Y0 = myfunctions.func1(X0)", "import myfunctions; X0 = %i" % (X0,))
print t.timeit()
print Y0
你可以看到我用了"X0 = %i" % (X0,)
来传入外部变量X0的真实值。
还有一点你可能想知道的是,如果你的主文件里有任何函数想在timeit
中使用,可以通过传递from __main__ import *
作为第二个参数,让timeit
识别它们。
如果你希望timeit
能够修改你的变量,就不要把字符串传给它。更方便的做法是传递可调用的对象。你应该传递一个可以改变你想要的变量的可调用对象。这样你就不需要setup
了。看:
from timeit import Timer
import myfunctions
def measure_me():
global Y0 #Make measure_me able to modify Y0
Y0 = myfunctions.func1(X0)
X0 = 1
Y0 = 0 #Have Y0 defined
t = Timer(measure_me)
print t.timeit()
print Y0
如你所见,我把print Y0
放在了print t.timeit()
之后,因为在执行之前,变量的值是不能被改变的!
你需要一个叫做 setup
的参数。试试这个:
Timer("Y0 = myfunctions.func1(X0)", setup="import myfunctions; X0 = 1")