2.12. Ciklusok

Egy ciklus ismételten futtatja ugyanazt a kódblokkot. A Pythonban két formája van: a while, amely addig fut, amíg egy feltétel igaz marad, és a for, amely végighalad egy szekvencia elemein.

Egymás melletti folyamatábrák. while: teszteld a feltételt, futtasd a törzset, ha igaz, ismételd. for: vedd a következő elemet az iterálható objektumból, futtasd a törzset, ismételd, amíg ki nem ürül.

A while folyamatosan tesztel egy feltételt; a for végighalad egy szekvencián, amíg az ki nem ürül.

2.12.1. while ciklusok

Egy while ciklus minden iteráció előtt teszteli a feltételét, és addig futtatja a törzset, amíg a teszt hamissá nem válik:

count = 0
while count < 5:
    print(count)
    count += 1

Kimenet:

0
1
2
3
4

Ha a feltétel kezdetben igaz, és sosem válik hamissá, a ciklus örökké fut. A while True: a fő ciklus szokásos megoldása, amelyből kifejezetten egy break lép ki:

while True:
    step()
    if done():
        break

2.12.2. for ciklusok

Egy for ciklus végighalad egy iterálható objektum elemein – legyen az lista, tuple, sztring, bytes, dict vagy bármi más, ami támogatja az iterációt:

for fruit in ["apple", "banana", "cherry"]:
    print(fruit)

Kimenet:

apple
banana
cherry

Ugyanez a forma működik egy sztringen is, ahol minden elem egy egykarakteres sztring:

for letter in "OpenMV":
    print(letter)

Kimenet:

O
p
e
n
M
V

Egy dict közvetlen iterálása a kulcsait adja vissza, beszúrási sorrendben:

for key in {"a": 1, "b": 2}:
    print(key)

Kimenet:

a
b

Minden menet a ciklusváltozóhoz (fruit, letter, key) köti a következő elemet. A ciklus végeztével a változó megtartja az utolsó iterációból származó értéket.

2.12.3. range

Numerikus tartomány feletti ciklusokhoz használd a range() függvényt:

  • range(stop) – 0, 1, …, stop - 1.

  • range(start, stop) – start, start + 1, …, stop - 1.

  • range(start, stop, step) – egyedi lépésközzel (a negatív értékek visszafelé számolnak).

for i in range(5):           # 0, 1, 2, 3, 4
    print(i)

for i in range(2, 8, 2):     # 2, 4, 6
    print(i)

for i in range(10, 0, -1):   # 10, 9, ..., 1
    print(i)

A range() lustán állítja elő az értékeket – nem épít fel listát a memóriában. Tényleges list előállításához csomagold be: list(range(10)).

2.12.4. enumerate

Amikor a ciklusnak az indexre és az elemre is szüksége van, az enumerate() (index, item) párokat ad vissza:

for i, name in enumerate(["a", "b", "c"]):
    print(i, name)
# 0 a
# 1 b
# 2 c

Az indexet nullától eltérő értékről indíthatod egy második argumentum átadásával: enumerate(items, start=1).

2.12.5. zip

Két (vagy több) iterálható objektum egymással lépést tartó bejárásához használd a zip() függvényt. Pozíciónként egy tuple-t ad vissza, és a legrövidebb bemenetnél megáll:

names  = ["alice", "bob", "carol"]
scores = [88, 92, 70]

for name, score in zip(names, scores):
    print(name, score)

Kimenet:

alice 88
bob 92
carol 70

2.12.6. Beágyazott értékadás a := operátorral

A rozmár (walrus) operátor := egy olyan értékadás, amely egyben kifejezés is. Egyszerre köt egy nevet és értékelődik ki ugyanarra az értékre. Egy while ciklusban ez a gyakori „olvass, ellenőrizz, törzs” mintát egyetlen sorba sűríti:

# without walrus
value = next_value()
while value is not None:
    process(value)
    value = next_value()

# with walrus
while (value := next_value()) is not None:
    process(value)

A két forma ugyanazt teszi. Nyúlj a := operátorhoz, ha az értékadás megkettőzése valóban rontja az olvashatóságot; ne nyúlj hozzá csak azért, hogy okosnak tűnj. A legtöbb pozícióban kötelezőek a zárójelek, hogy a kifejezés egyértelmű maradjon.