Как использовать вызываемый в качестве установки с timeit.Timer? - PullRequest
2 голосов
/ 12 мая 2010

Я хочу определить время кода, который зависит от настроек. Код установки выглядит примерно так:

>>> b = range(1, 1001)

И код, который я хочу для времени, выглядит примерно так:

>>> sorted(b)

За исключением того, что мой код использует функцию, отличную от отсортированной. Но это сейчас не важно.

Во всяком случае, я знаю, как рассчитать этот код, пока я передаю строки в timeit:

>>> import timeit
>>> t = timeit.Timer("sorted(b)", "b = range(1, 1001)")
>>> min(t.repeat(3, 100))

Как использовать вызываемый параметр установки и поместить его в пространство имен, к которому может обращаться вызываемый stmt?

Другими словами, как мне сделать то же самое, что и в приведенном выше коде, но с вызываемыми элементами, а не со строками, содержащими вызываемые элементы?

Кстати, здесь большая цель - повторно использовать код из моих модульных тестов для измерения производительности:

import unittest
class TestSorting(unittest.TestCase):

    def setUp(self):
        self.b = range(1, 1001)

    def test_sorted(self):
        sorted(self.b)

Я ожидаю немного поработать. Настройка timeit должна создать экземпляр TestSorting, и каким-то образом код stmt должен будет использовать этот конкретный экземпляр.

Как только я пойму, как установка timeit помещает вещи в то же пространство имен, что и stmt timeit, я посмотрю, как преобразовать экземпляры unittest.TestCase во что-то, что может быть направлено прямо в timeit.Timer.

Мэтт

Ответы [ 2 ]

1 голос
/ 12 мая 2010

Я задал вариант этого вопроса здесь, а также получил ответ, который не решил мою проблему. Я считаю, что мы оба не можем сформулировать проблему в терминах Pythonic.

Я не знаю, если это взлом, обходной путь или как это должно быть сделано, но это работает:

>>> import timeit
>>> b = range(1, 1001)
>>> t = timeit.Timer('sorted(b)', setup='from __main__ import b')
>>> t.repeat(3, 100)
[0.0024309158325195312, 0.0024671554565429688, 0.0024020671844482422]
# was it really running 'sorted(b)'? let's compare'
>>> t = timeit.Timer('pass', setup='from __main__ import b')
>>> t.repeat(3, 100) 
[3.0994415283203125e-06, 2.1457672119140625e-06, 1.9073486328125e-06] 
# teeny times for 'pass', 'sorted(b)' took more time

Я прочитал timeit.py, он работает путем создания оператора, а затем вызывает eval () для него, используя новые пространства имен, которые (по-видимому) не связаны с вашим основным пространством имен. Обратите внимание, что, поскольку sorted является встроенным, eval'ed выражение внутри timeit.repeat() имеет доступ к имени; если бы это был ваш def, вам бы пришлось from __main__ import b, myfunc.

Я надеюсь, что есть более правильный способ достижения цели.

1 голос
/ 12 мая 2010

В версии 2.6 вы можете «просто сделать это» за документы :

Изменено в версии 2.6 : stmt и setup параметры теперь также могут принимать объекты, которые можно вызывать без аргументы. Это будет вставлять звонки их в функции таймера, который будет затем будет казнен timeit(). Заметка что временные накладные расходы немного больше в этом случае из-за дополнительные вызовы функций.

Вы застряли, используя старую версию Python? В этом случае я бы предложил взять timer.py исходники Python 2.6 и «перенести» их обратно в версию, с которой вы застряли - не должно быть трудностей, если эта версия 2.5 (становится сложнее, чем дальше вам нужно возвращаться вовремя, конечно). Обычно я бы не рекомендовал это для «производственного» кода, но он вполне подходит для кода, который поддерживает тестирование, отладку, измерения производительности и т. П.

...