2.12. Pętle

Pętla wielokrotnie wykonuje ten sam blok kodu. Python ma dwie postacie: while, która działa tak długo, jak warunek pozostaje prawdziwy, oraz for, która przechodzi przez elementy sekwencji.

Schematy blokowe obok siebie. while: sprawdź warunek, wykonaj ciało, jeśli prawdziwy, powtórz. for: pobierz następny element z iterowalnego obiektu, wykonaj ciało, powtarzaj aż do wyczerpania.

while wciąż sprawdza warunek; for przechodzi przez sekwencję aż do jej wyczerpania.

2.12.1. pętle while

Pętla while sprawdza swój warunek przed każdą iteracją i wykonuje ciało, dopóki test nie stanie się fałszywy:

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

Wynik:

0
1
2
3
4

Jeśli warunek jest prawdziwy na początku i nigdy nie staje się fałszywy, pętla działa w nieskończoność. while True: to standardowy idiom pętli głównej, opuszczanej jawnie przez break:

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

2.12.2. pętle for

Pętla for przechodzi przez elementy obiektu iterowalnego – listy, krotki, łańcucha znaków, bajtów, słownika lub czegokolwiek innego, co obsługuje iterację:

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

Wynik:

apple
banana
cherry

Ten sam kształt działa na łańcuchu znaków, gdzie każdym elementem jest jednoznakowy łańcuch:

for letter in "OpenMV":
    print(letter)

Wynik:

O
p
e
n
M
V

Bezpośrednia iteracja po słowniku zwraca jego klucze w kolejności wstawiania:

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

Wynik:

a
b

Każdy przebieg wiąże zmienną pętli (fruit, letter, key) z następnym elementem. Po zakończeniu pętli zmienna zachowuje wartość z ostatniej iteracji.

2.12.3. range

Do pętli po zakresie liczbowym użyj range():

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

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

  • range(start, stop, step) – z niestandardowym krokiem (wartości ujemne odliczają w dół).

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)

range() produkuje wartości leniwie – nie buduje listy w pamięci. Aby uzyskać rzeczywistą list, opakuj go: list(range(10)).

2.12.4. enumerate

Gdy pętla potrzebuje zarówno indeksu, jak i elementu, enumerate() zwraca pary (index, item):

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

Rozpocznij indeksowanie od wartości innej niż zero, przekazując drugi argument: enumerate(items, start=1).

2.12.5. zip

Aby przechodzić przez dwa (lub więcej) obiekty iterowalne równolegle, użyj zip(). Zwraca on jedną krotkę na pozycję i zatrzymuje się na najkrótszym wejściu:

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

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

Wynik:

alice 88
bob 92
carol 70

2.12.6. Przypisanie inline za pomocą :=

Operator morsa := to przypisanie będące jednocześnie wyrażeniem. Wiąże nazwę i równocześnie ewaluuje się do tej samej wartości. W pętli while pozwala to złożyć powszechny wzorzec „odczytaj, sprawdź, wykonaj ciało” w jeden wiersz:

# 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)

Obie postacie robią to samo. Sięgaj po :=, gdy powielenie przypisania rzeczywiście pogarsza czytelność; nie używaj go tylko po to, by się popisać. Nawiasy są wymagane w większości pozycji, aby wyrażenie pozostało jednoznaczne.