https://docs.python.org/3/library/functions.html#iter
Funkcja iter(X) zwraca obiekt iteratora, utworzony na bazie obiektu X. Obiekt X musi wspierać protokół iteracji (metoda __iter__, obiekt dostarcza swój iterator) lub protokół sekwencji (metoda __getitem__ z argumentami typu int startującymi od 0).
Druga wersja wywołania funkcji iter() zwraca iterator zbudowany na bazie obiektu wywoływalnego i strażnika (wartość kończąca iterację).
# Składnia.
# iter(iterable) zwraca iterator
# iter(callable, sentinel) zwraca iterator
# Iterator bazujący na sekwencji.
it1 = iter([1, 2]) # list_iterator object in Py3 (lists have __iter__)
it2 = iter("abcd") # str_iterator object in Py3 (strings have __iter__)
it3 = iter(it2) # all iterators are also iterables
assert it3 is it2
# Kiedy mamy iterator, to jedyne co możemy zrobić, to pobierać kolejne elementy
# aż do wyczerpania iteratora, a wtedy pojawi się wyjątek StopIteration.
print(next(it1)) # 1
print(next(it1)) # 2
print(next(it1)) # StopIteration
# Przykład obiektu wspierającego protokół sekwencji.
class Dumb:
def __init__(self, sequence):
self.data = sequence
def __getitem__(self, n):
return self.data[n]
x = Dumb("word")
#print(dir(x)) # nie ma __iter__ i __next__
print(x[1]) # zwraca 'o'
#print(x[10]) # IndexError: string index out of range
#len(x) # AttributeError: Dumb instance has no attribute __len__
for item in x: # można iterować po x
print(item)
y = iter(x) # można jawnie utworzyć iterator
#print(dir(y)) # pojawia się __iter__ i __next__ (Py3.7)
print(next(y)) # w
print(next(y)) # o
print(next(y)) # r
print(next(y)) # d
print(next(y)) # StopIteration
# Przygotowanie iteratora na bazie obiektu wywoływalnego.
# Obiekt wywoływalny to zwykle coś więcej niż funkcja,
# bo posiada i utrzymuje swój stan pomiędzy wywołaniami.
class MyInt:
"""Klasa do tworzenia obiektów wywoływalnych, zwracających kolejne int."""
def __init__(self):
self.n = 0
def __call__(self):
self.n = self.n + 1
return self.n
x = MyInt() # x to MyInt instance, obiekt wywoływalny
print(x()) # 1
print(x()) # 2
# Przygotowanie iteratora, który zakończy pracę, jeżeli x zwróci 10.
y = iter(x, 10) # y to callable-iterator object
for i in y: # zwróci 3,4,5,6,7,8,9 (bez 10)
print(i)
# wartości 1 i 2 były wykorzystane wcześniej przez print(),
# wartość 10 jest wykorzystana na zatrzymanie iteratora
#print(next(y)) # wyzwala StopIteration
print(x()) # 11, obiekt wywoływalny jest aktywny
import itertools # Różne wersje iteratora nieskończonego zwracającego zawsze wartość 0. iter_zeros1 = iter(int, 1) # int() zwraca 0 iter_zeros2 = iter((lambda: 0), 1) # funkcja bez argumentów to obiekt wywoływalny iter_zeros3 = itertools.cycle([0]) # itertools.cycle(sequence) iter_zeros4 = itertools.repeat(0) # itertools.repeat(x, times=5)
import random # Przykłady iteratorów nieskończonych. it = iter(MyInt(), 0) # zwraca 1,2,3,... z obiektu wywoływalnego it = (random.choice(range(7)) for _ in iter(int, 1)) # przypadkowy dzień tygodnia it = iter(lambda: random.choice(range(7)), -1) # jw