Python Timeit и «глобальное имя ... не определено» - PullRequest
6 голосов
/ 04 января 2012

У меня проблема с функцией timit для оптимизации кода. Например, я пишу функции с параметрами в файле, назовем его 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 ]

6 голосов
/ 04 января 2012

Вам нужен setup параметр.Попробуйте:

Timer("Y0 = myfunctions.func1(X0)", setup="import myfunctions; X0 = 1")
4 голосов
/ 04 января 2012

Причина того, что 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, вы можете timeit распознать их, передав from __main__ import * в качестве второго аргумента.


Если вы хотите, чтобы 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(), так как до выполнения вы не можете изменить его значение!

...