2.11. Feltételes utasítások¶
Egy feltételes utasítás csak akkor futtat le egy kódblokkot, ha valamilyen teszt igazra értékelődik ki. A kulcsszó az if, amelyet opcionálisan egy vagy több elif („else if”) ág és egy záró else követhet.
n = 42
if n > 0:
print("positive")
elif n < 0:
print("negative")
else:
print("zero")
Az egyes ágak törzse minden, ami alá behúzással kerül (megegyezés szerint négy szóköz). A Python sorrendben végigjárja az ágakat, lefuttatja az elsőt, amelynek a tesztje igaz, a többit pedig kihagyja. Az else blokk csak akkor fut le, ha minden megelőző teszt hamis volt; ez mindig opcionális.
Mindig csak egyetlen ág fut le. A tesztek fentről lefelé értékelődnek ki, amíg az egyik sikeres nem lesz; a többit a rendszer kihagyja.¶
2.11.1. Igazságérték¶
Egy if tesztjének nem kell True vagy False értéket visszaadnia – bármilyen érték igaz értékűnek (truthy) vagy hamis értékűnek (falsy) számít. A hamis értékű értékek a következők:
Minden más igaz értékű. Ez lehetővé teszi tömör tesztek írását:
if name: # false on empty string
print("hello", name)
if items: # false on empty list, dict, etc.
process(items)
Vedd figyelembe, hogy az igazságérték megváltoztatja a jelentést. Az if value: nem ugyanaz, mint az if value is not None: – az első akkor is hamis, amikor a value értéke 0 vagy "". Amikor valóban azt érted, hogy „pontosan None ez”, használd kifejezetten az is None / is not None formát.
2.11.2. Ternáris kifejezések¶
Egy feltételes utasítás megjelenhet egy kifejezésen belül is:
label = "even" if n % 2 == 0 else "odd"
Így olvasandó: „a label értéke "even" ha n % 2 == 0 különben "odd"„. Kényelmes egysorosokhoz; bármi, ami egy sornál hosszabb, könnyebben olvasható teljes if utasítással.
2.11.3. Beágyazás és korai visszatérések¶
A feltételes utasítások tetszőlegesen mélyen beágyazhatók, de a behúzás minden további rétege nehezebben olvashatóvá tesz egy függvényt. Az alábbi példa négy feltételt ellenőriz, mielőtt elvégezné a valódi munkát, és a hasznos sort négy behúzásnyi mélyen hagyja eltemetve:
def process(item):
if item is not None:
if item.is_valid():
if item.size() > 0:
if item.owner == "me":
return do_the_work(item)
return None
Két minta lapítja ki az ilyen jellegű kódot.
2.11.3.1. Korai visszatérések őrfeltételekhez¶
Kezeld először minden „kiszállási” esetet, mindegyiket saját return utasítással, hogy a fő logika a külső behúzási szinten maradjon. Minden őrfeltétel így olvasandó: „ez nem olyan eset, amelyet kezelünk; lépj ki”:
def process(item):
if item is None:
return None
if not item.is_valid():
return None
if item.size() == 0:
return None
if item.owner != "me":
return None
return do_the_work(item)
A „fő útvonal” most egyetlen sor a függvény alján, nem pedig négy réteg belsejébe temetve. Ezt a stílust néha őrfeltétel-mintának (guard clause) nevezik.
2.11.3.2. Tesztek kombinálása az and / or operátorokkal¶
Amikor több feltételnek is teljesülnie kell ugyanahhoz az ághoz, kombináld őket az and operátorral a beágyazás helyett. Azok a feltételek, amelyek egyenként, önállóan kiváltják az ágat, az or operátorral kombinálhatók:
# all must hold -- use `and`
if user.is_admin() and user.has_permission("write") and not locked:
save()
# any one of them is enough -- use `or`
if c == " " or c == "\t" or c == "\n":
whitespace_count += 1
Mindkét forma rövidre zár, így a jobb oldalon lévő költséges ellenőrzés csak akkor fut le, amikor a bal oldali olcsóbb ellenőrzések még nem rendezték a kérdést.