compare_functions
- это неправильная функция для декорирования, потому что вы хотите, чтобы каждая из функций была передана в compare_functions
, а не compare_functions
сама.
Я нахожу ее более полезно использовать временный код с помощью диспетчера контекста.
import time
import contextlib
class TimeResult:
def __init__(self):
self._start = None
self._stop = None
def start(self):
self._start = time.perf_counter()
def stop(self):
self._stop = time.perf_counter()
@property
def result(self):
if self._start is None or self._stop is None:
return None
return self._stop - self._start
Это простой класс, свойство result
которого равно None
до тех пор, пока вы не вызовете оба метода start
и stop
( желательно в таком порядке)
@contextlib.contextmanager
def timeit():
t = TimeResult()
t.start()
yield t
t.stop()
Это создает менеджер контекста, который выдает объект TimeResult
, чьи методы start
и stop
вызываются при входе и при выходе из оператора with
соответственно.
def compare_functions(f1, f2):
with timeit() as t1:
f1()
print(f'Function 1 took {t1.result} seconds')
with timeit() as t2:
f2()
print(f'Function 2 took {t2.result} seconds')
compare_functions
принимает две функции для вызова, и каждый раз из них менеджер контекста timeit
. Когда каждая функция завершается, сообщается прошедшее время.
Затем
def print_msg(msg):
print(msg)
compare_functions(lambda: print_msg("hi"), lambda: print_msg("see ya"))
принимает две функции для вызова и времени.
Кроме того, вы можете передать функции времени и аргументы отдельно, и пусть compare_functions
объединит их.
def compare_functions(f_and_args_1, f_and_args_2):
f1, *args1 = f_and_args1
f2, *args2 = f_and_args2
with timeit() as t1:
f1(*args1)
print(f'{f1.__name__} took {t1.result} seconds')
with timeit() as t2:
f2(*args2)
print(f'{f2.__name__} took {t2.result} seconds')
compare_functions((print_msg, "hi"), (print_msg, "see ya"))