Last modified: September 22, 2024

This article is written in: 馃嚨馃嚤

Iteratory

Iteratory to fundamentalny koncept w j臋zyku Python, szczeg贸lnie w kontek艣cie p臋tli i struktur iterowalnych, takich jak listy, krotki czy zbiory. Python traktuje iteratory jako narz臋dzie do sukcesywnego uzyskiwania kolejnych element贸w z kolekcji danych w spos贸b zorganizowany, z mo偶liwo艣ci膮 zatrzymania i wznowienia procesu iteracji. W tej rozbudowanej wersji om贸wimy, jak dzia艂aj膮 iteratory, jak je tworzy膰, oraz jak s膮 wykorzystywane przez r贸偶ne mechanizmy Pythonowe, takie jak p臋tla for oraz generatory.

Poj臋cie iterowalno艣ci

W Pythonie obiekt jest iterowalny (ang. iterable), je艣li mo偶na po nim iterowa膰, tj. mo偶na sukcesywnie uzyskiwa膰 kolejne elementy. Obiekty te musz膮 implementowa膰 metod臋 __iter__(), kt贸ra zwraca iterator. Iterator jest obiektem, kt贸ry realizuje protok贸艂 iteratora, to znaczy posiada metod臋 __next__(), kt贸ra zwraca kolejny element w sekwencji.

Typowe struktury danych, takie jak listy, krotki, zbiory czy s艂owniki, s膮 iterowalne, co pozwala na u偶ycie p臋tli for do iteracji nad ich elementami. W tle dzia艂a tutaj mechanizm oparty na iteratorach.

Iteracja przez list臋

for elem in [1, 2, 3]:
    print(elem)

Powy偶sza p臋tla for w rzeczywisto艣ci wywo艂uje na li艣cie metod臋 __iter__(), kt贸ra zwraca iterator. Iterator ten posiada metod臋 __next__(), kt贸ra jest wywo艂ywana w ka偶dej iteracji w celu uzyskania kolejnego elementu listy.

Przyk艂ad r臋cznego u偶ycia iteratora

Mo偶emy bezpo艣rednio pracowa膰 z iteratorem, korzystaj膮c z funkcji wbudowanej iter() oraz metody next().

lista = [1, 2, 3]
iterator = iter(lista)  # Tworzy iterator z listy
print(next(iterator))   # 1
print(next(iterator))   # 2
print(next(iterator))   # 3
# Kolejne wywo艂anie next() wyrzuci wyj膮tek StopIteration

Kiedy iterator nie ma ju偶 kolejnych element贸w do zwr贸cenia, wywo艂anie next() powoduje wygenerowanie wyj膮tku StopIteration. Jest to sygna艂 dla p臋tli for, aby zako艅czy膰 iteracj臋.

Protok贸艂 iteratora

Protok贸艂 iteratora w Pythonie sk艂ada si臋 z dw贸ch kluczowych metod:

Zrozumienie tych metod jest kluczowe, je艣li chcemy definiowa膰 w艂asne iteratory.

Tworzenie w艂asnych iterator贸w

Aby stworzy膰 w艂asny iterator, konieczne jest zdefiniowanie klasy z implementacj膮 metod __iter__() i __next__(). Przyk艂ad klasy b臋d膮cej iteratorem:

class MojaKolekcja:
    def __init__(self):
        self.elementy = [1, 2, 3]
        self.indeks = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.indeks < len(self.elementy):
            wynik = self.elementy[self.indeks]
            self.indeks += 1
            return wynik
        else:
            raise StopIteration

kolekcja = MojaKolekcja()
for elem in kolekcja:
    print(elem)

Dzia艂anie powy偶szego przyk艂adu:

  1. Metoda __iter__() zwraca referencj臋 do samego siebie, co oznacza, 偶e instancja klasy jest tak偶e swoim w艂asnym iteratorem.
  2. Metoda __next__() zwraca kolejny element z listy, a gdy wszystkie elementy zostan膮 wyczerpane, rzuca wyj膮tek StopIteration, ko艅cz膮c iteracj臋.

Teoretyczne uzasadnienie iterator贸w

Iteratory w Pythonie opieraj膮 si臋 na koncepcji leniwej ewaluacji (ang. lazy evaluation). W przeciwie艅stwie do standardowych kolekcji, kt贸re przechowuj膮 wszystkie swoje elementy w pami臋ci, iterator nie generuje element贸w z g贸ry, ale produkuje je na 偶膮danie. Pozwala to na efektywne wykorzystanie pami臋ci, zw艂aszcza w przypadku du偶ych kolekcji danych lub niesko艅czonych sekwencji.

Matematycznie iteratory mo偶na postrzega膰 jako funkcje, kt贸re na ka偶dym kroku zwracaj膮 kolejny element z pewnej sekwencji, bez potrzeby przechowywania jej pe艂nej reprezentacji w pami臋ci. Dzi臋ki temu mo偶liwa jest np. praca z niesko艅czonymi sekwencjami.

Generatory jako iteratory

Generatory s膮 specjalnym rodzajem iterator贸w, kt贸re s膮 definiowane za pomoc膮 funkcji wykorzystuj膮cych s艂owo kluczowe yield. Generatory upraszczaj膮 proces tworzenia iterator贸w, automatycznie zarz膮dzaj膮c stanem iteracji i rzucaniem wyj膮tku StopIteration po zako艅czeniu iteracji.

Przyk艂ad prostego generatora:

def generator_liczb():
    for i in range(3):
        yield i

for liczba in generator_liczb():
    print(liczba)

Wyja艣nienie dzia艂ania generator贸w:

  1. Ka偶de wywo艂anie yield zatrzymuje wykonanie funkcji i zwraca warto艣膰. Wznowienie nast臋puje w miejscu, w kt贸rym funkcja zosta艂a przerwana.
  2. Generator zachowuje sw贸j stan pomi臋dzy kolejnymi wywo艂aniami, co czyni go bardzo efektywnym przy implementacji z艂o偶onych iteracji.

Wyj膮tek StopIteration w praktyce

Ka偶dy iterator po wyczerpaniu swoich element贸w rzuca wyj膮tek StopIteration, kt贸ry informuje o zako艅czeniu iteracji. Jest to mechanizm kontrolny, kt贸ry pozwala p臋tlom for automatycznie wykrywa膰, kiedy przesta膰 iterowa膰.

P臋tla for automatycznie obs艂uguje wyj膮tek StopIteration i przerywa iteracj臋, co czyni ten mechanizm intuicyjnym i 艂atwym w u偶yciu. Je艣li jednak korzystamy z iteracji r臋cznie za pomoc膮 next(), musimy sami zadba膰 o odpowiedni膮 obs艂ug臋 wyj膮tku.

iterator = iter([1, 2, 3])
while True:
    try:
        element = next(iterator)
        print(element)
    except StopIteration:
        break

Korzy艣ci z u偶ywania iterator贸w

Z艂o偶one generatory i przep艂yw danych

Generatory mo偶na r贸wnie偶 艂膮czy膰, tworz膮c bardziej z艂o偶one strumienie danych. Na przyk艂ad, mo偶na stworzy膰 generator, kt贸ry pobiera dane z innego generatora, przetwarza je i zwraca przetworzony wynik.

def podwoj_wartosci(generator):
    for

 wartosc in generator:
        yield wartosc * 2

generator_liczb = (i for i in range(5))
podwojony_generator = podwoj_wartosci(generator_liczb)

for wartosc in podwojony_generator:
    print(wartosc)

Powy偶szy przyk艂ad pokazuje, jak mo偶na tworzy膰 z艂o偶one przep艂ywy danych, gdzie generatory s膮 u偶ywane do transformacji danych w spos贸b p艂ynny i leniwy.

Spis Tre艣ci

    Iteratory
    1. Poj臋cie iterowalno艣ci
      1. Iteracja przez list臋
    2. Przyk艂ad r臋cznego u偶ycia iteratora
    3. Protok贸艂 iteratora
    4. Tworzenie w艂asnych iterator贸w
    5. Teoretyczne uzasadnienie iterator贸w
    6. Generatory jako iteratory
    7. Wyj膮tek StopIteration w praktyce
    8. Korzy艣ci z u偶ywania iterator贸w
    9. Z艂o偶one generatory i przep艂yw danych