Pętle

Pętle to podstawowy mechanizm sterowania przepływem programu. Umożliwiają wielokrotne wykonywanie fragmentu kodu w sposób kontrolowany – do momentu spełnienia określonego warunku albo dla każdego elementu danej kolekcji. Bez nich praktycznie nie da się pisać programów przetwarzających dane, wykonujących obliczenia iteracyjne czy operujących na strukturach takich jak listy i słowniki. Zagadnienie Pętle Python obejmuje kilka konstrukcji językowych oraz dodatkowe mechanizmy pomocnicze, które razem tworzą spójny system iteracji.

Pętle Python – konstrukcja for jako podstawowy mechanizm iteracji po sekwencjach i iteratorach

Czym jest pętla for i jak działa w Pythonie

W Pythonie pętla for nie jest klasyczną pętlą licznikową znaną z języka C. Jest to konstrukcja iteracyjna oparta na protokole iteratora. Oznacza to, że nie operuje bezpośrednio na liczniku, lecz na obiekcie dostarczającym kolejne wartości.

Ogólna postać:

for zmienna in obiekt_iterowalny:
instrukcje

Działanie:

  1. Python pobiera iterator z obiektu (wywołując wewnętrznie metodę __iter__()).
  2. W każdej iteracji wywoływana jest metoda __next__().
  3. Jeśli pojawi się wyjątek StopIteration, pętla kończy działanie.

Przykład:

for x in [10, 20, 30]:
print(x)

Każdy element listy zostaje przypisany do zmiennej x.

Iteracja po różnych typach danych

Pętla for działa z każdym obiektem iterowalnym:

  • listy
  • krotki
  • napisy
  • zbiory
  • słowniki
  • zakresy (range)
  • pliki
  • generatory

Iteracja po napisie:

for znak in "abc":
print(znak)

Iteracja po słowniku:

d = {"a": 1, "b": 2}
for klucz in d:
print(klucz)

Aby uzyskać pary klucz-wartość:

for klucz, wartosc in d.items():
print(klucz, wartosc)

Funkcja range() jako generator liczb

range() zwraca obiekt typu range, który generuje liczby całkowite w określonym zakresie.

Postacie:

range(stop)
range(start, stop)
range(start, stop, krok)

Przykład:

for i in range(5):
print(i)

Wynik:
0 1 2 3 4

range() nie tworzy listy – generuje wartości dynamicznie, co jest oszczędne pamięciowo.

Iteracja z indeksem – enumerate()

Częsty problem: potrzebny jest zarówno element, jak i jego indeks.

lista = ["a", "b", "c"]for i, wartosc in enumerate(lista):
print(i, wartosc)

enumerate() zwraca iterator par (indeks, element).

Zagnieżdżone pętle for

Możliwe jest zagnieżdżanie pętli:

for i in range(3):
for j in range(2):
print(i, j)

Złożoność czasowa rośnie multiplikatywnie. Dla dwóch pętli o długości n mamy złożoność O(n²).

Pętle Python – konstrukcja while, warunki zakończenia i kontrola przepływu programu

Podstawowa konstrukcja while

Pętla while wykonuje blok kodu tak długo, jak warunek logiczny jest prawdziwy.

while warunek:
instrukcje

Przykład:

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

Warunek sprawdzany jest przed każdą iteracją.

Ryzyko pętli nieskończonej

Jeżeli warunek nigdy nie stanie się fałszywy, pętla będzie wykonywana bez końca:

while True:
print("dziala")

Taka konstrukcja jest używana celowo w serwerach, pętlach głównych programów czy systemach wbudowanych.

Instrukcja break

Natychmiastowe przerwanie pętli.

while True:
x = int(input())
if x == 0:
break

Po wykonaniu break sterowanie przechodzi za blok pętli.

Instrukcja continue

Pomija bieżącą iterację i przechodzi do następnej.

for i in range(5):
if i == 2:
continue
print(i)

Wynik: 0 1 3 4

Klauzula else w pętlach

Python posiada mniej znany mechanizm else po pętli.

for i in range(5):
print(i)
else:
print("koniec")

Blok else wykona się, jeśli pętla zakończyła się naturalnie (bez break).

Przykład z wyszukiwaniem:

liczby = [1, 3, 5, 7]for x in liczby:
if x == 4:
print("znaleziono")
break
else:
print("nie znaleziono")

Pętle Python – zaawansowane mechanizmy: list comprehensions, generatory, iteratory własne i aspekty wydajnościowe

List comprehensions jako skrócona forma pętli

Składnia:

[wyrazenie for element in sekwencja if warunek]

Przykład:

kwadraty = [x*x for x in range(10)]

Z warunkiem:

parzyste = [x for x in range(20) if x % 2 == 0]

Mechanizm:

  1. Tworzona jest nowa lista.
  2. Iteracja odbywa się podobnie jak w for.
  3. Wyrażenie generuje element wynikowy.

List comprehensions są zwykle szybsze niż ręczne dodawanie elementów przez append().

Generator expressions

Różnią się nawiasami:

gen = (x*x for x in range(10))

Nie tworzą listy w pamięci. Wartości generowane są na żądanie.

Użycie:

for x in gen:
print(x)

Własne iteratory

Aby obiekt był iterowalny, musi implementować:

  • __iter__()
  • __next__()

Minimalny przykład:

class Licznik:
def __init__(self, max):
self.max = max
self.i = 0 def __iter__(self):
return self def __next__(self):
if self.i < self.max:
self.i += 1
return self.i - 1
else:
raise StopIteration

Użycie:

for x in Licznik(3):
print(x)

Funkcja iter() i next()

Możliwe jest ręczne sterowanie iteracją:

it = iter([1,2,3])
print(next(it))
print(next(it))

Po wyczerpaniu elementów pojawi się StopIteration.

Porównanie z C i C++

W C klasyczna pętla licznikowa:

#include <stdio.h>int main() {
int i;
for(i = 0; i < 5; i++) {
printf("%d\n", i);
}
return 0;
}

W C++:

#include <iostream>
using namespace std;int main() {
for(int i = 0; i < 5; i++) {
cout << i << endl;
}
}

W Pythonie:

for i in range(5):
print(i)

Python nie udostępnia bezpośrednio zmiennej sterującej jako mechanizmu językowego — opiera się na iteratorach.

Wydajność i złożoność

  • Pętla for po liście: O(n)
  • Zagnieżdżone pętle: O(n²), O(n³), itd.
  • List comprehension: często minimalnie szybsze
  • Generator: oszczędność pamięci kosztem niewielkiego narzutu wywołań

Koszt operacji wewnątrz pętli dominuje nad samą konstrukcją pętli.

Uwagi praktyczne i typowe błędy

  1. Modyfikowanie listy podczas iteracji może prowadzić do nieprzewidywalnych efektów.
  2. Brak inkrementacji w while powoduje pętlę nieskończoną.
  3. Nadużywanie zagnieżdżonych pętli prowadzi do problemów wydajnościowych.
  4. W wielu przypadkach operacje na całych kolekcjach (sum, map, any, all) są czytelniejsze niż ręczne pętle.
  5. Zbyt skomplikowane list comprehensions obniżają czytelność.

Pętle stanowią rdzeń sterowania przepływem w Pythonie. Konstrukcje for, while, mechanizm iteratorów oraz generatory tworzą spójny model iteracji oparty na protokole iteratora. Zrozumienie ich działania na poziomie wewnętrznym pozwala pisać kod przewidywalny, wydajny i poprawny logicznie.