Podstawowym sposobem umieszczania kodu samosprawdzającego moduł Pythona jest wykorzystanie zmiennej __name__. Bardziej zaawansowane narzędzia testujące oferują moduły doctest i unittest z biblioteki standardowej. Moduł unittest2 to backport nowych możliwości z Pythona 2.7 do Pythona 2.4-2.6. Moduły nose i pytest to dodatkowe narzędzia do pisania testów z lekką składnią.
https://docs.python.org/3/library/doctest.html
def average(values):
"""Oblicza średnią arytmetyczną listy liczb.
>>> average([20, 30, 70])
40.0
"""
return sum(values, 0.0) / len(values)
if __name__ == "__main__":
import doctest
doctest.testmod() # automatyczne sprawdzanie wbudowanych testów
# Sprawdzanie przykładów podanych w pliku tekstowym.
# Zawartość pliku jet traktowana jako jeden wielki docstring.
import doctest
doctest.testfile("example.txt")
Moduł pytest należy do biblioteki standardowej od Pythona 3.6.
# Przykładowy plik z testami test_sample.py ('test' w nazwie pliku).
def inc(x):
return x + 1
def test_answer(): # 'test' w nazwie funkcji
assert inc(3) == 5 # intentional error, 'assert' is used
# Testy uruchamiamy w powłoce systemu operacyjnego poleceniem 'pytest',
# tak działa 'discovery mode'.
Moduł timeit służy do testowania czasu wykonania małych kawałków kodu. Do testowania większych bloków kodu istnieją inne narzędzia: profile, pstats.
Głównym elementem modułu jest klasa Timer(stmt="pass", setup="pass").
Metoda repeat(self, repeat=3, number=1000000) -
wywołanie timeit() kilka razy (zwraca listę wyników).
Metoda timeit(self, number=1000000) -
najpierw następuje pojedyncze wykonanie poleceń z setup,
a potem number wykonań instrukcji z stmt.
import timeit # help(timeit) # Często przydaje się średnik do rozdzielania poleceń. t1 = timeit.Timer(stmt="t=a ; a=b ; b=t", setup="a=1 ; b=2") t2 = timeit.Timer(stmt="(a,b) = (b,a)", setup="a=1 ; b=2") print(t1.timeit()) # domyślnie milion wykonań print(t2.timeit()) print(t2.repeat(5)) # zwraca listę 5 wyników print(min(t2.repeat(10))) # to jest zwykle miarodajne, a nie średnia
import timeit # Można budować polecenia wielowierszowe. s = """\ pierwszy wiersz drugi wiersz """ t = timeit.Timer(stmt=s) print(t.timeit())
import random
import timeit
def mysort(L, left, right):
L[left: right+1] = sorted(L[left: right+1])
lista = list(range(1000))
random.shuffle(lista)
t1 = timeit.Timer(stmt="mysort(lista, 0, len(lista)-1)",
setup="from __main__ import mysort, lista")
print(t1.timeit(1)) # pojedyncze wykonanie
# Od Pythona 2.6 można przekazywać obiekty callable bez argumentów.
import random
import timeit
def mysort(L, left, right):
L[left: right+1] = sorted(L[left: right+1])
lista = list(range(1000))
random.shuffle(lista)
t1 = timeit.Timer(lambda: mysort(lista, 0, len(lista)-1))
print(t1.timeit(1)) # pojedyncze wykonanie
https://docs.python.org/3/library/enum.html
https://docs.python.org/3/howto/enum.html
PEP 0435 - Adding an Enum type to the Python standard library.
Typ Enum został dodany do Pythona 3.4
from enum import Enum
# from enum import IntEnum # można porównywać z int
class Color(Enum):
RED = 1 # zalecane jest użycie dużych liter do stałych
GREEN = 2
BLUE = 3
for c in Color: # iteracja po enum
print(c)
#print(c.name, c.value)
# Color.RED
# Color.GREEN
# Color.BLUE
# Dostęp do koloru czerwonego:
Color(1) # <Color.red: 1>
Color["RED"] # jw