Powtarzanie

🎯 Po co Ci to?

Wszystko, co komputery robią imponującego — przeszukanie miliona rekordów, narysowanie miliona pikseli, sprawdzenie miliona haseł na sekundę — to zasługa jednej umiejętności: powtarzania bez znudzenia. Człowiek przy setnym powtórzeniu robi błąd; komputer przy miliardowym jest tak samo świeży. Pętla to sposób, w jaki zaprzęgasz tę nadludzką cierpliwość do pracy. To także miejsce, gdzie powstaje najwięcej błędów programistycznych świata — poznasz je z imienia, zanim popełnisz.

✅ Czego się nauczysz

Po tej jednostce potrafisz:

  • używać pętli for z range („powtórz dla kolejnych liczb") i while („powtarzaj, dopóki");
  • budować w pętli sumy i liczniki oraz śledzić je tabelką;
  • rozpoznawać dwa klasyczne błędy pętli: pomyłkę o jeden i pętlę nieskończoną.

📘 Wyjaśnienie

Pętla for — znana liczba obrotów. Chcesz coś zrobić dla kolejnych liczb? range produkuje ciąg, a for przechodzi po nim:

for i in range(1, 6):
    print(i, "x 7 =", i * 7)

Program wypisze tabliczkę mnożenia przez 7 dla $i = 1, 2, 3, 4, 5$. Tak — do pięciu, nie do sześciu: range(1, 6) zawiera początek, ale nie zawiera końca. Ta konwencja (matematyk powie: przedział lewostronnie domknięty) jest w Pythonie żelazna i na początku wkurzająca; ma jednak głęboki sens, który docenisz przy listach: range(0, n) daje dokładnie $n$ obrotów.

Suma i licznik — dwa wzorce, które musisz mieć we krwi. Większość pętli świata robi jedno z dwojga: coś sumuje albo coś zlicza. Schemat jest zawsze ten sam: przed pętlą wyzeruj, w pętli dokładaj:

suma = 0
for i in range(1, 101):
    suma = suma + i
print(suma)       # 5050 — kłania się Gauss z działu 1

Pętla while — nieznana liczba obrotów. Czasem nie wiesz z góry, ile razy powtórzyć — wiesz tylko, kiedy przestać. while powtarza blok, dopóki warunek jest prawdziwy:

kapital = 1000
lata = 0
while kapital < 2000:
    kapital = kapital * 1.05     # 5% odsetek rocznie
    lata = lata + 1
print("Podwojenie po", lata, "latach")

Nie wiadomo z góry, ile obrotów wykona ta pętla — i właśnie dlatego użyliśmy while, nie for. (Wynik: 15 lat. Procent składany to wzrost wykładniczy z jednostki 2.7 — tu pracuje dla Ciebie.)

💭 Pomyśl: Co się stanie, jeśli w pętli powyżej zapomnisz linijki kapital = kapital * 1.05?

Sprawdź odpowiedź

Warunek kapital < 2000 będzie wiecznie prawdziwy (kapitał stoi na 1000), więc pętla będzie się kręcić bez końca — program „zawiesi się". To pętla nieskończona, drugi z wielkich klasyków błędów. Reguła bezpieczeństwa: w ciele while coś musi przybliżać warunek do fałszu. Gdy program „wisi", pierwszym podejrzanym jest zawsze warunek pętli. (Awaryjne wyjście: Ctrl+C w konsoli przerywa program.)

warunekspełniony?TAKciało pętlipowrót(kolejny obrót)NIEdalej
Schemat blokowy pętli while: romb z warunkiem, gałąź TAK prowadzi przez ciało pętli i strzałką wraca nad romb, gałąź NIE wychodzi dalej — powtarzanie to strzałka w górę. · rys. własny

🧮 Prześledź

Klasyka sprawdzianów — co wypisze ten program?

s = 0
i = 1
while i <= 4:
    s = s + i * i
    i = i + 1
print(s, i)
obrót warunek i <= 4 s po obrocie i po obrocie
przed pętlą — 0 1
1 ? ? ?
2 ? ? ?
3 ? ? ?
4 ? ? ?
5 ? — —
Sprawdź odpowiedź

Obroty: (1) $1\le4$ prawda, $s = 0+1 = 1$, $i=2$; (2) prawda, $s = 1+4 = 5$, $i=3$; (3) prawda, $s = 5+9 = 14$, $i=4$; (4) prawda ($4 \le 4$!), $s = 14+16 = 30$, $i=5$; (5) $5\le4$ fałsz — koniec. Wypisze 30 5. Dwie rzeczy, które mylą ludzi: obrót czwarty wykonuje się (równość wchodzi w <=), a i po pętli ma wartość 5, nie 4 — pętla kończy się dopiero, gdy warunek zdąży być fałszywy.

⚠️ Uwaga, pułapka

Pomyłka o jeden (ang. off-by-one) to najczęstszy błąd w historii programowania: pętla wykonuje się raz za dużo albo raz za mało. Źródła: mylenie < z <=, zapominanie, że range nie zawiera końca, zerowanie licznika w złym miejscu. Szczepionka jest jedna i znasz ją z działu 1: prześledź brzegi — pierwszy obrót i ostatni obrót, ręcznie. Trzydzieści sekund tabelki oszczędza pół godziny wpatrywania się w kod.

💻 Kod krok po kroku

Połączmy pętlę z decyzją — program zliczający, ile spośród 5 wpisanych ocen to oceny bardzo dobre lub wyższe:

licznik = 0
for i in range(5):                    # 5 obrotów: i = 0, 1, 2, 3, 4
    ocena = int(input("Ocena: "))
    if ocena >= 5:                    # decyzja WEWNĄTRZ pętli
        licznik = licznik + 1
print("Piątek i szóstek:", licznik)

Zauważ podwójne wcięcie licznik = licznik + 1 — ta linijka należy do if, który należy do for. Wcięcia w Pythonie to nie estetyka, to składnia: mówią, co jest w czym. Przesuniesz linijkę o poziom w lewo — zmienisz działanie programu, nie jego wygląd.

🛠️ Teraz Ty

Zaprogramuj zgadywankę z działu 1 — w wersji, w której komputer myśli liczbę (na sztywno, np. sekret = 37), a użytkownik zgaduje: pętla while pyta o liczbę, odpowiada „za dużo"/„za mało" i liczy próby; po trafieniu wypisuje gratulacje i liczbę prób. Przetestuj na sobie strategią połowienia — czy mieścisz się w 7 próbach dla zakresu 1–100?

📐 Definicje tej lekcji

  • for i in range(a, b) — pętla o znanej liczbie obrotów: $i = a, a+1, \dots, b-1$ (bez $b$!).
  • while warunek — pętla „dopóki": obraca się, póki warunek prawdziwy; coś w środku musi go kiedyś obalić.
  • Pomyłka o jeden / pętla nieskończona — dwa klasyczne błędy pętli; lekarstwem śledzenie brzegów i kontrola warunku.

📌 Najważniejsze w pigułce

  • for gdy wiesz ile razy, while gdy wiesz do kiedy.
  • Wzorce suma/licznik: wyzeruj przed, dokładaj w środku, odczytaj po.
  • range(a, b) nie zawiera b; po while licznik ma wartość, która obaliła warunek.

🎒 Zadania

  1. Ile razy wykona się ciało każdej pętli? (a) for i in range(10), (b) for i in range(3, 10), (c) while 2 > 1 z ciałem print("hej"), (d) for i in range(5, 5).
Wskazówka i odpowiedź

(a) 10 (od 0 do 9). (b) 7 (od 3 do 9 — koniec minus początek). (c) nieskończenie wiele — warunek nigdy nie zgaśnie (pętla nieskończona „na życzenie"). (d) zero razy — zakres pusty; pętla, która nie wykona się ani razu, to legalny i częsty brzeg (pamiętasz pustą listę z działu 1?).

  1. Napisz program wypisujący wszystkie dzielniki wczytanej liczby $n$ oraz ich liczbę. Ile obrotów wykonuje Twoja pętla dla $n = 1,000,000$ i czy dałoby się mniej?
Wskazówka i odpowiedź

Wersja wprost: for d in range(1, n + 1): if n % d == 0: ... — milion obrotów. Da się o połowę mniej (dzielniki poza $n$ samym kończą się na $n/2$), a naprawdę sprytnie — sprawdzać tylko do $\sqrt{n}$ i dopisywać dzielniki parami ($d$ oraz $n/d$): dla miliona to ledwie 1000 obrotów. Ten pomysł zrobi zawrotną karierę w dziale 4 przy badaniu pierwszości.

  1. Suma 0.1 dodawanej sto razy w pętli daje w Pythonie 9.99999999999998. Połącz wiedzę z jednostki 2.4 z dzisiejszą i wyjaśnij, czemu pętla „ujawniła" błąd, którego jedno dodawanie nie pokazywało.
Wskazówka i odpowiedź

0.1 jest w pamięci drobnie niedokładne (błąd przybliżenia ~$10^{-17}$); pojedyncze dodawanie tego nie ujawnia, bo błąd ginie w zaokrągleniu wyświetlania. Pętla kumuluje: sto maleńkich błędów sumuje się do wielkości widocznej w wyniku. To miniatura historii rakiety Patriot — i powód, dla którego pętle finansowe liczy się na groszach całkowitych.

🔍 Sprawdź, czy umiesz

  • Wybrać między for a while dla opisanego zadania i uzasadnić.
  • Prześledzić tabelką pętlę z sumą i licznikiem, łącznie z wartościami po pętli.
  • Wskazać w cudzym kodzie ryzyko pomyłki o jeden.

Ucz się tej jednostki z asystentem