Pythonové iterátory (__iter__ a __next__): Ako to používať a prečo?

Iterátory sú objekty, ktoré je možné iterovať. V tomto tutoriáli sa dozviete, ako iterátor funguje a ako si môžete vytvoriť svoj vlastný iterátor pomocou metód __iter__ a __next__.

Video: Pythonové iterátory

Iterátory v Pythone

Iterátory sú všade v Pythone. Elegantne sú implementované v rámci forslučiek, porozumení, generátorov atď., Ale sú skryté na očiach.

Iterátor v Pythone je jednoducho objekt, ktorý je možné iterovať. Objekt, ktorý vráti údaje, jeden prvok po druhom.

Technicky vzaté, Python iterátor objekt musí implementovať dve špeciálne metódy, __iter__()a __next__(), kolektívne nazvaný Iterator protokol .

Objekt sa nazýva iterovateľný, ak z neho môžeme získať iterátor. Väčšina vstavaných kontajnerov v Pythone ako: list, n-tica, reťazec atď. Sú iterovateľné.

iter()Funkcia (ktorá zase volá __iter__()metódu) vracia iterátor z nich.

Iterácia Iterátorom

Pomocou tejto next()funkcie manuálne iterujeme všetky položky iterátora. Keď dôjdeme na koniec a už nebudeme musieť vrátiť žiadne údaje, vyvolá to StopIterationvýnimku. Nasleduje prí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ýkon

 4 7 0 3 Traceback (posledný posledný hovor): súbor „“, riadok 24, v nasledujúcej (my_iter) StopIteration

Elegantnejším spôsobom automatickej iterácie je použitie cyklu for. Pomocou toho môžeme iterovať akýkoľvek objekt, ktorý dokáže vrátiť iterátor, napríklad zoznam, reťazec, súbor atď.

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

Práca cyklu for pre iterátory

Ako vidíme vo vyššie uvedenom príklade, forslučka bola schopná automaticky iterovať zoznamom.

V skutočnosti môže forslučka iterovať cez ktorúkoľvek opakovateľnú položku. Pozrime sa podrobnejšie na to, ako je forslučka v Pythone skutočne implementovaná.

 for element in iterable: # do something with element

Je skutočne implementovaný ako.

 # 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 vnútorne forslučka vytvára iterátorový objekt iter_objvyvolaním iter()iterovateľného objektu.

Je iróniou, že táto forslučka je vlastne nekonečná while slučka.

Vo vnútri slučky volá, next()aby získal ďalší prvok, a vykoná telo forslučky s touto hodnotou. Potom, čo sa všetky položky vyčerpajú, StopIterationsa zdvihne, čo je vnútorne zachytené a slučka končí. Upozorňujeme, že prejde akýkoľvek iný druh výnimky.

Budovanie vlastných iterátorov

Vytvorenie iterátora od nuly je v Pythone ľahké. Len musíme implementovať __iter__()aj na __next__()metódy.

__iter__()Metóda vracia objekt Iterator sám. V prípade potreby je možné vykonať určitú inicializáciu.

__next__()Metóda musí vrátiť ďalšiu položku v poradí. Po dosiahnutí konca a v ďalších výzvach sa musí zvýšiť StopIteration.

Tu ukážeme príklad, ktorý nám dá ďalšiu mocninu 2 v každej iterácii. Silový exponent začína od nuly po číslo nastavené používateľom.

Pokiaľ nemáte predstavu o objektovo orientovanom programovaní, navštívte 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ýkon

 1 2 4 8 Traceback (posledný hovor naposledy): Súbor "/home/bsoyuj/Desktop/Untitled-1.py", riadok 32, v tlačenej podobe (ďalší (i)) Súbor "", riadok 18, v __next__ zvýšiť StopIteration StopIterácia

Môžeme tiež použiť forslučku na iteráciu nad našou triedou iterátorov.

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

Python nekonečné iterátory

Nie je potrebné, aby sa položka v iteračnom objekte musela vyčerpať. Môže existovať nekonečné množstvo iterátorov (ktoré nikdy nekončia). Pri manipulácii s takýmito iterátormi musíme byť opatrní.

Tu je jednoduchý príklad na demonštráciu nekonečných iterátorov.

Funkciu vstavanej iter()funkcie je možné volať pomocou dvoch argumentov, kde prvý argument musí byť volaný objekt (funkcia) a druhý je sentinel. Iterátor volá túto funkciu, kým sa vrátená hodnota nerovná sentinelu.

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

Vidíme, že int()funkcia vždy vráti 0. Takže jej odovzdaním ako iter(int,1)vrátime iterátor, ktorý volá, int()kým sa vrátená hodnota nebude rovnať 1. Toto sa nikdy nestane a dostaneme nekonečný iterátor.

Môžeme si tiež zostaviť vlastné nekonečné iterátory. Nasledujúci iterátor teoreticky vráti všetky nepárne čí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ážka cyklu by bola nasledovná.

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

A tak ďalej…

Pri iterácii nad týmito typmi nekonečných iterátorov buďte opatrní.

Výhodou používania iterátorov je, že šetria zdroje. Ako je uvedené vyššie, mohli by sme získať všetky nepárne čísla bez toho, aby sme uložili celý číselný systém do pamäte. V konečnej pamäti môžeme mať (teoreticky) nekonečné položky.

Existuje jednoduchší spôsob, ako vytvoriť iterátory v Pythone. Ak sa chcete dozvedieť viac, navštívte: Generátory Pythonu využívajúce výnos.

Zaujímavé články...