Отримання "глобальної назви" foo "не визначено" за допомогою timeit Python


92

Я намагаюся з'ясувати, скільки часу потрібно для виконання оператора Python, тому я заглянув в Інтернет і виявив, що стандартна бібліотека забезпечує модуль під назвою timeit, який передбачає робити саме це:

import timeit

def foo():
    # ... contains code I want to time ...

def dotime():
    t = timeit.Timer("foo()")
    time = t.timeit(1)
    print "took %fs\n" % (time,)

dotime()

Однак це призводить до помилки:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in dotime
  File "/usr/local/lib/python2.6/timeit.py", line 193, in timeit
    timing = self.inner(it, self.timer)
  File "<timeit-src>", line 6, in inner
NameError: global name 'foo' is not defined

Я все ще новачок у Python, і я не до кінця розумію всі проблеми, пов’язані із сферою застосування, але я не знаю, чому цей фрагмент не працює. Будь-які думки?

Відповіді:


93

Змінити цей рядок:

t = timeit.Timer("foo()")

До цього:

t = timeit.Timer("foo()", "from __main__ import foo")

Перевірте посилання, яке ви вказали внизу.

Щоб надати модулю timeit доступ до визначених вами функцій, ви можете передати параметр налаштування, який містить оператор імпорту:

Я просто тестував його на своїй машині, і він працював зі змінами.


28
Це працює! Однак це досить дурний дизайн інтерфейсу, якщо мені доводиться як подавати команду, яку я хочу, як час, як рядок, так і імпортувати основний модуль для її роботи.
Kyle Cronin

2
Розміщення імен Python для мене є абсолютно божевільним. Я припускаю, що це має сенс для певного виду розуму, але такий розум я не маю, яким я випадково володію. Дякую $ DEITY за Рубі, у моєму випадку.
womble

5
womble, це бородавка, а не загальна проблема простору імен python. Основна тема: writeonly.wordpress.com/2008/09/12/… має посилання на інші дискусії з цього приводу.
Gregg Lind

1
@Gregg Посилання більше не доступне (помилка 404). Що було в цій дискусії?
ovgolovin

2
всі ці посилання мертві
ендоліт

25

За допомогою Python 3 ви можете використовувати globals=globals()

t = timeit.Timer("foo()", globals=globals())

З документації :

Інший варіант - перейти globals()до globalsпараметра, що призведе до виконання коду у вашому поточному глобальному просторі імен. Це може бути зручніше, ніж індивідуальне зазначення імпорту


3
Працює лише для Python 3. globalsне параметр для Python 2timeit
tony_tiger

21

Ви можете спробувати цей хак:

import timeit

def foo():
    print 'bar'

def dotime():
    t = timeit.Timer("foo()")
    time = t.timeit(1)
    print "took %fs\n" % (time,)

import __builtin__
__builtin__.__dict__.update(locals())

dotime()

1
Цей хакер чудово підходить, якщо вам інакше потрібен складний код налаштування.
Luís Marques

Краще, ніж альтернативний варіант стартового коду, наведений в інших відповідях (тобто краще, ніж t = timeit.Timer("foo()", "from __main__ import foo")). Якщо ви хочете протестувати кілька різних функцій, це значно заощадить набір тексту!
A.Sommerh

1
У мене близько 20 імпортів, тому передача їх як аргумент швидко стає брудною. Цей хак чудовий!
kramer65

7
Чудово! На python3, однак, вам потрібні import builtinsта "вбудовані .__ dict __. Update (
local

Чи можете ви визначити час кількома функціями у функції Time ()?
edo101

8
t = timeit.Timer("foo()", "from __main__ import foo")

Оскільки timeit не має вашої речі в обсязі.


0

додайте у налаштування "import thisfile;"

тоді, коли ви викликаєте функцію налаштування myfunc (), використовуйте "thisfile.myfunc ()"

наприклад "thisfile.py"

def myfunc():

 return 5

def testable(par):

 pass



t=timeit.timeit(stmt="testable(v)",setup="import thisfile; v=thisfile.myfunc();").repeat(10)

print( t )
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.