2.13. Controlul buclelor

Două cuvinte-cheie schimbă modul în care rulează o buclă:

  • break – iese imediat din buclă.

  • continue – sare peste restul iterației curente și începe următoarea.

Ambele se aplică buclei celei mai interioare în care apar.

2.13.1. break

Folosește break pentru a opri o buclă de îndată ce o condiție este îndeplinită. Tiparul clasic „caută și oprește”:

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

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

Într-o buclă while True:, break este modul în care se încheie bucla:

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

2.13.2. continue

Folosește continue pentru a sări peste restul corpului și a trece la următoarea iterație. Util pentru filtrarea elementelor în interiorul unei bucle:

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

Același efect poate fi scris ca un bloc if în jurul restului corpului. continue este uneori mai clar atunci când condiția de sărire este mai ușor de formulat de la început decât condiția de păstrare.

În interiorul unei bucle, continue joacă același rol ca un return timpuriu într-o funcție: sare peste cazurile pe care nu le tratezi și menține activitatea principală aliniată la indentarea exterioară. Bucla de tip filtrează-și-procesează este forma canonică:

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

Linia indentată process(item) reprezintă activitatea propriu-zisă; fiecare gardă de mai sus precizează exact ce elemente sunt sărite.

2.13.3. else pe o buclă

Atât for cât și while acceptă un bloc else opțional. Acesta rulează atunci când bucla se finalizează fără a întâlni un break. Cea mai frecventă utilizare este o buclă de căutare care dorește o variantă de rezervă în cazul în care nu s-a găsit nimic:

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

Dacă se declanșează un break, blocul else este sărit. Citește construcția ca „for X in Y: …; sau, dacă nu am ieșit niciodată, fă Z.”

2.13.4. Tipare comune de bucle

Câteva tipare apar frecvent în scripturile reale:

  • Interogare (polling) – așteaptă ca o condiție să devină adevărată înainte de a continua. Corpul folosește pass, instrucțiunea no-op din Python; fiecare bloc indentat trebuie să conțină cel puțin o instrucțiune, iar pass este modul de a spune „nu face nimic aici”:

    while not ready():
        pass
    proceed()
    
  • Mașină cu stări – o singură buclă while True: care alege ce să facă în funcție de o variabilă de stare. Utilă atunci când activitatea se împarte clar în câteva faze denumite:

    state = "header"
    for line in lines:
        if state == "header":
            if line.startswith("---"):
                state = "body"
        elif state == "body":
            print(line)
    
  • Acumulare – construiește un rezultat în timp ce parcurgi o secvență:

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

    Multe bucle de acumulare au un echivalent pe o singură linie folosind o funcție încorporată. Apelează la funcția încorporată atunci când există una potrivită:

    • sum() – adună fiecare element dintr-un iterabil.

    • max() / min() – cel mai mare sau cel mai mic element.

    • any()True dacă cel puțin un element este adevărat (truthy).

    • all()True doar când fiecare element este adevărat (truthy).

    • sorted() – o listă nouă cu elementele în ordine.

    • len() – numărul de elemente (acolo unde iterabilul își cunoaște lungimea).

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

    Versiunea încorporată este mai scurtă, mai clară și de obicei mai rapidă decât scrierea manuală a aceleiași bucle.