5.3. Optimization Timeit
5.3.1. Timeit - Programmatic use
timeit
from timeit import timeit
setup = """name = 'Alice'"""
stmt = """result = f'Hello {name}'"""
duration = timeit(stmt, setup, number=10000)
print(duration)
# 0.0005737080000000061
from timeit import timeit
setup = """
firstname = 'Alice'
lastname = 'Apricot'
"""
TEST = dict()
TEST[0] = 'name = f"{firstname} {lastname}"'
TEST[1] = 'name = "{0} {1}".format(firstname, lastname)'
TEST[2] = 'name = firstname + " " + lastname'
TEST[3] = 'name = " ".join([firstname, lastname])'
for stmt in TEST.values():
duration = timeit(stmt, setup, number=10000)
print(f'{duration:.5}\t{stmt}')
# 0.00071559 name = f"{firstname} {lastname}"
# 0.0026514 name = "{0} {1}".format(firstname, lastname)
# 0.001015 name = firstname + " " + lastname
# 0.0013494 name = " ".join([firstname, lastname])
from timeit import timeit
def factorial(n: int) -> int:
if n == 0:
return 1
else:
return n * factorial(n-1)
duration = timeit(
stmt='factorial(500); factorial(400); factorial(450)',
globals=globals(),
number=10000,
)
duration = round(duration, 6)
print(f'factorial time: {duration} seconds')
# factorial time: 2.845382 seconds
5.3.2. Timeit - Console use
python3 -m timeit -n100000 -r100 --setup='name="Alice"' 'output = f"Hello {name}"'
# 100000 loops, best of 100: 55.9 nsec per loop
python3 -m timeit -n100000 -r100 --setup='name="Alice"' 'output = "Hello {name}".format(name=name)'
# 100000 loops, best of 100: 327 nsec per loop
python3 -m timeit -n100000 -r100 --setup='name="Alice"' 'output = "Hello %s" % name'
# 100000 loops, best of 100: 124 nsec per loop
-n N, --number=N
how many times to execute 'statement'
-r N, --repeat=N
how many times to repeat the timer (default 5)
-s S, --setup=S
statement to be executed once initially (default pass)
-p, --process
measure process time, not wallclock time, using time.process_time() instead of time.perf_counter(), which is the default
-u, --unit=U
specify a time unit for timer output; can select nsec, usec, msec, or sec
-v, --verbose
print raw timing results; repeat for more digits precision
-h, --help
print a short usage message and exit
5.3.3. Assignments
# FIXME: Write tests
# %% About
# - Name: Memoization
# - Difficulty: easy
# - Lines: 5
# - Minutes: 5
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% English
# 1. Create empty `dict` named `CACHE`
# 2. In the dictionary, we will store the results of calculating
# the function for the given parameters:
# - key: function argument
# - value: calculation result
# 3. Modify function `factorialA(n: int)`
# 4. Before running the function, check if the result has already
# been calculated:
# - if so, return data from `CACHE`
# - if not, calculate, update `CACHE` and return the value
# 5. Compare the speed of operation
# 6. Run doctests - all must succeed
# %% Polish
# 1. Stwórz pusty `dict` o nazwie `CACHE`
# 2. W słowniku będziemy przechowywali wyniki wyliczenia funkcji
# dla zadanych parametrów:
# - klucz: argument funkcji
# - wartość: wynik obliczeń
# 3. Zmodyfikuj funkcję `factorialA(n: int)`
# 4. Przed uruchomieniem funkcji, sprawdź czy wynik został już
# wcześniej obliczony:
# - jeżeli tak, to zwraca dane z `CACHE`
# - jeżeli nie, to oblicza, aktualizuje `CACHE` i zwraca wartość
# 5. Porównaj prędkość działania
# 6. Uruchom doctesty - wszystkie muszą się powieść
# %% Doctests
"""
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`
# %% Imports
from timeit import timeit
import sys
# %% Types
# %% Data
sys.setrecursionlimit(5000)
# %% Result
def factorialA(n: int) -> int:
return 1 if n==0 else n*factorialA(n-1)
# Do not modify anything below
def factorialB(n: int) -> int:
return 1 if n==0 else n*factorialB(n-1)
durationA = timeit(
stmt='factorialA(50); factorialA(40); factorialA(45); factorialA(35)',
globals={'factorialA': factorialA},
number=10000,
)
durationB = timeit(
stmt='factorialB(50); factorialB(40); factorialB(45); factorialB(35)',
globals={'factorialB': factorialB},
number=10000,
)
times_faster = durationB / durationA
print(f'factorialA time: {durationA:.4f} seconds')
print(f'factorialB time: {durationB:.4f} seconds')
print(f'Cached solution is {times_faster:.0f} times faster')
# factorialA time: 0.0654 seconds
# factorialB time: 0.0658 seconds
# Cached solution is 1 times faster