Pythonové iterátory (__iter__ a __next__): Jak to používat a proč?

Iterátory jsou objekty, na které lze iterovat. V tomto kurzu se dozvíte, jak iterátor funguje a jak si můžete vytvořit svůj vlastní iterátor pomocí metod __iter__ a __next__.

Video: Pythonové iterátory

Iterátory v Pythonu

Iterátoři jsou v Pythonu všude. Jsou elegantně implementovány do forsmyček, porozumění, generátorů atd., Ale jsou skryty na očích.

Iterátor v Pythonu je jednoduše objekt, na který lze iterovat. Objekt, který vrátí data, jeden prvek po druhém.

Technicky vzato, objekt iterátoru Pythonu musí implementovat dvě speciální metody __iter__()a __next__()souhrnně se nazývá iterátorový protokol .

Objekt se nazývá iterovatelný, pokud z něj můžeme získat iterátor. Většina vestavěných kontejnerů v Pythonu jako: list, n-tice, řetězec atd. Jsou iterovatelné.

iter()Funkce (která zase volá __iter__()metodu) vrací iterátor z nich.

Iterace Iterátorem

Tuto next()funkci používáme k ruční iteraci všech položek iterátoru. Když dojdeme na konec a již nebudou vrácena žádná další data, vyvolá to StopIterationvýjimku. Následuje příklad.

 # define a list my_list = (4, 7, 0, 3) # get an iterator using iter() my_iter = iter(my_list) # iterate through it using next() # Output: 4 print(next(my_iter)) # Output: 7 print(next(my_iter)) # next(obj) is same as obj.__next__() # Output: 0 print(my_iter.__next__()) # Output: 3 print(my_iter.__next__()) # This will raise error, no items left next(my_iter)

Výstup

 4 7 0 3 Traceback (poslední hovor poslední): Soubor „“, řádek 24, v dalším (my_iter) StopIteration

Elegantnějším způsobem automatické iterace je použití smyčky for. Pomocí toho můžeme iterovat jakýkoli objekt, který může vrátit iterátor, například seznam, řetězec, soubor atd.

 >>> for element in my_list:… print(element)… 4 7 0 3

Práce cyklu for pro iterátory

Jak vidíme ve výše uvedeném příkladu, forsmyčka dokázala automaticky iterovat seznamem.

Ve skutečnosti může forsmyčka iterovat přes jakoukoli iterovatelnou. Podívejme se blíže na to, jak je forsmyčka ve skutečnosti implementována v Pythonu.

 for element in iterable: # do something with element

Ve skutečnosti je implementován jako.

 # create an iterator object from that iterable iter_obj = iter(iterable) # infinite loop while True: try: # get the next item element = next(iter_obj) # do something with element except StopIteration: # if StopIteration is raised, break from loop break

Takže interně forsmyčka vytváří iterátorový objekt iter_objvoláním iter()iterovatelného.

Je ironií, že tato forsmyčka je vlastně nekonečná smyčka while.

Uvnitř smyčky volá next()získat další prvek a provede tělo forsmyčky s touto hodnotou. Poté, co se všechny položky vyčerpají, StopIterationje zvednuto, což je interně zachyceno a smyčka končí. Všimněte si, že projde jakýkoli jiný druh výjimky.

Vytváření vlastních iterátorů

Vytvoření iterátoru od nuly je v Pythonu snadné. Jen musíme implementovat __iter__()i na __next__()metody.

__iter__()Metoda vrací objekt iterátoru sám. V případě potřeby lze provést určitou inicializaci.

__next__()Metoda musí vrátit další položku v pořadí. Po dosažení cíle a v dalších výzvách se musí zvýšit StopIteration.

Zde ukážeme příklad, který nám dá další sílu 2 v každé iteraci. Výkonový exponent začíná od nuly až po číslo nastavené uživatelem.

Pokud nemáte představu o objektově orientovaném programování, navštivte Python Object-Oriented Programming.

 class PowTwo: """Class to implement an iterator of powers of two""" def __init__(self, max=0): self.max = max def __iter__(self): self.n = 0 return self def __next__(self): if self.n <= self.max: result = 2 ** self.n self.n += 1 return result else: raise StopIteration # create an object numbers = PowTwo(3) # create an iterable from the object i = iter(numbers) # Using next to get to the next iterator element print(next(i)) print(next(i)) print(next(i)) print(next(i)) print(next(i))

Výstup

 1 2 4 8 Traceback (poslední hovor poslední): Soubor "/home/bsoyuj/Desktop/Untitled-1.py", řádek 32, v tisku (další (i)) Soubor "", řádek 18, v __next__ zvýšit StopIteration StopIterace

Můžeme také použít forsmyčku k iteraci nad naší třídou iterátorů.

 >>> for i in PowTwo(5):… print(i)… 1 2 4 8 16 32

Python Infinite Iterators

Není nutné, aby byla položka v iterátorovém objektu vyčerpána. Může existovat nekonečný počet iterátorů (které nikdy nekončí). Při manipulaci s takovými iterátory musíme být opatrní.

Zde je jednoduchý příklad pro demonstraci nekonečných iterátorů.

Funkci vestavěné iter()funkce lze volat pomocí dvou argumentů, přičemž prvním argumentem musí být volaný objekt (funkce) a druhým je sentinel. Iterátor volá tuto funkci, dokud se vrácená hodnota nebude rovnat sentinelu.

 >>> int() 0 >>> inf = iter(int,1) >>> next(inf) 0 >>> next(inf) 0

Vidíme, že int()funkce vždy vrátí 0. Takže její předání jako iter(int,1)vrátí iterátor, který volá, int()dokud se vrácená hodnota nebude rovnat 1. To se nikdy nestane a získáme nekonečný iterátor.

Můžeme také vytvořit vlastní nekonečné iterátory. Následující iterátor teoreticky vrátí všechna lichá čísla.

 class InfIter: """Infinite iterator to return all odd numbers""" def __iter__(self): self.num = 1 return self def __next__(self): num = self.num self.num += 2 return num

Ukázkový běh by byl následující.

 >>> a = iter(InfIter()) >>> next(a) 1 >>> next(a) 3 >>> next(a) 5 >>> next(a) 7

A tak dále…

Při iteraci nad těmito typy nekonečných iterátorů buďte opatrní, abyste zahrnuli podmínku ukončení.

Výhodou použití iterátorů je, že šetří prostředky. Jak je ukázáno výše, mohli bychom získat všechna lichá čísla bez uložení celého číselného systému do paměti. V konečné paměti můžeme mít (teoreticky) nekonečné položky.

Existuje jednodušší způsob vytváření iterátorů v Pythonu. Další informace najdete na stránce: Generátory Pythonu využívající výnos.

Zajímavé články...