Często słyszysz, że Python zachęca stylu EAFP („łatwiej jest prosić o przebaczenie niż o pozwolenie”) zamiast stylu LBYL („spójrz, zanim skoczysz ”). Dla mnie to kwestia wydajności i czytelności.
W twoim przykładzie (powiedz, że zamiast zwracać listę lub pusty ciąg, funkcja miała zwrócić listę lub None
), jeśli spodziewasz się, że 99% czasu result
faktycznie będzie zawierało coś iterowalnego, zastosowałbym try/except
podejście. Będzie szybciej, jeśli wyjątki są naprawdę wyjątkowe. Jeśli result
jest to None
więcej niż 50% czasu, użycie if
jest prawdopodobnie lepsze.
Aby wesprzeć to kilkoma pomiarami:
>>> import timeit
>>> timeit.timeit(setup="a=1;b=1", stmt="a/b") # no error checking
0.06379691968322732
>>> timeit.timeit(setup="a=1;b=1", stmt="try:\n a/b\nexcept ZeroDivisionError:\n pass")
0.0829463709378615
>>> timeit.timeit(setup="a=1;b=0", stmt="try:\n a/b\nexcept ZeroDivisionError:\n pass")
0.5070195056614466
>>> timeit.timeit(setup="a=1;b=1", stmt="if b!=0:\n a/b")
0.11940114974277094
>>> timeit.timeit(setup="a=1;b=0", stmt="if b!=0:\n a/b")
0.051202772912802175
Tak więc, podczas gdy if
wyciąg zawsze kosztuje, skonfigurowanie try/except
bloku jest prawie darmowe . Ale kiedy Exception
faktycznie nastąpi, koszt jest znacznie wyższy.
Morał:
- Jest całkowicie OK (i „pythonowy”) w użyciu
try/except
do sterowania przepływem,
- ale ma to sens najbardziej, gdy
Exception
są naprawdę wyjątkowe.
Z dokumentacji Pythona:
EAFP
Łatwiej prosić o przebaczenie niż o pozwolenie. Ten wspólny styl kodowania w Pythonie zakłada istnienie prawidłowych kluczy lub atrybutów i wyłapuje wyjątki, jeśli założenie okaże się fałszywe. Ten czysty i szybki styl charakteryzuje się obecnością wielu
try
i except
wypowiedzi. Technika kontrastuje ze
stylem LBYL wspólnym dla wielu innych języków, takich jak C.