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 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__, __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__, __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/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) # 1 i 2 było wykorzystane wcześniej przez print(), # 10 wykorzystane na zatrzymanie iteratora #print(next(y)) # wyzwala StopIteration print(x()) # 11, obiekt wywoływalny jest aktywny
import itertools 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 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