2.13. Sterowanie pętlą

Dwa słowa kluczowe zmieniają sposób działania pętli:

  • break – natychmiast opuszcza pętlę.

  • continue – pomija pozostałą część bieżącej iteracji i rozpoczyna następną.

Oba odnoszą się do najbardziej wewnętrznej pętli, w której się pojawiają.

2.13.1. break

Użyj break, aby zatrzymać pętlę natychmiast po spełnieniu warunku. Klasyczny wzorzec „szukaj i zatrzymaj się”:

found = None
for item in items:
    if matches(item):
        found = item
        break

if found is not None:
    print("found:", found)

W pętli while True: to właśnie break kończy jej działanie:

while True:
    line = next_line()
    if line == "quit":
        break
    process(line)

2.13.2. continue

Użyj continue, aby pominąć pozostałą część ciała pętli i przejść do następnej iteracji. Przydatne do filtrowania elementów wewnątrz pętli:

for n in numbers:
    if n < 0:
        continue            # skip negatives
    print(n)

Ten sam efekt można uzyskać, umieszczając blok if wokół reszty ciała pętli. continue bywa czytelniejsze, gdy warunek pominięcia łatwiej sformułować od razu niż warunek zachowania elementu.

Wewnątrz pętli continue pełni tę samą rolę co wczesne return w funkcji: pomija przypadki, których nie obsługujesz, i utrzymuje główną pracę na płaskim, zewnętrznym poziomie wcięcia. Pętla typu filtruj-i-przetwarzaj to kanoniczny kształt:

for item in items:
    if item is None:
        continue
    if not item.is_valid():
        continue
    process(item)

Wcięty wiersz process(item) to właściwa praca; każda wcześniejsza straż dokładnie określa, które elementy zostają pominięte.

2.13.3. else w pętli

Zarówno for, jak i while akceptują opcjonalny blok else. Wykonuje się on, gdy pętla zakończy się bez napotkania break. Najczęstszym zastosowaniem jest pętla wyszukiwania, która potrzebuje rozwiązania awaryjnego, jeśli nic nie znaleziono:

for item in items:
    if matches(item):
        print("found:", item)
        break
else:
    print("no match")

Jeśli break zadziała, blok else zostaje pominięty. Konstrukcję czytaj jako „for X in Y: …; a w przeciwnym razie, jeśli nigdy nie wyszliśmy, wykonaj Z”.

2.13.4. Częste wzorce pętli

Kilka wzorców pojawia się często w rzeczywistych skryptach:

  • Odpytywanie (polling) – czekanie, aż jakiś warunek stanie się prawdziwy, zanim przejdziemy dalej. Ciało pętli używa pass, instrukcji pustej (no-op) w Pythonie; każdy wcięty blok musi zawierać co najmniej jedną instrukcję, a pass to sposób na powiedzenie „nic tu nie rób”:

    while not ready():
        pass
    proceed()
    
  • Maszyna stanów – pojedyncza pętla while True:, która wybiera, co zrobić, na podstawie zmiennej stanu. Przydatna, gdy praca dzieli się jasno na kilka nazwanych faz:

    state = "header"
    for line in lines:
        if state == "header":
            if line.startswith("---"):
                state = "body"
        elif state == "body":
            print(line)
    
  • Akumulacja – budowanie wyniku podczas przechodzenia przez sekwencję:

    total = 0
    for x in samples:
        total += x
    mean = total / len(samples)
    

    Wiele pętli akumulujących ma jednowierszowy odpowiednik wykorzystujący funkcję wbudowaną. Sięgnij po funkcję wbudowaną, gdy któraś pasuje:

    • sum() – dodaje każdy element iterowalnego obiektu.

    • max() / min() – największy lub najmniejszy element.

    • any()True, jeśli co najmniej jeden element jest prawdziwy (truthy).

    • all()True tylko wtedy, gdy każdy element jest prawdziwy (truthy).

    • sorted() – nowa lista z elementami w kolejności.

    • len() – liczba elementów (gdy obiekt iterowalny zna swoją długość).

    >>> samples = [3, 1, 4, 1, 5, 9, 2, 6]
    >>> sum(samples)
    31
    >>> sum(samples) / len(samples)        # mean
    3.875
    >>> max(samples)
    9
    >>> min(samples)
    1
    >>> sorted(samples)
    [1, 1, 2, 3, 4, 5, 6, 9]
    >>> any([False, False, True])
    True
    >>> all([True, True, False])
    False
    

    Wersja wbudowana jest krótsza, czytelniejsza i zwykle szybsza niż ręczne pisanie tej samej pętli.