Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> Python

Python-iterators: hoe ze werken en hoe je je eigen maakt

Python-iterators

Ontdek hoe Python-iterators functioneren, hoe je ze doorloopt met for-lussen of de next()-functie, en hoe je custom of oneindige iterators maakt met het iterator-protocol.

Video: Python-iterators

Iterators in Python

Iterators zijn alomtegenwoordig in Python. Ze liggen ten grondslag aan for-lussen, list comprehensions, generators en veel ingebouwde datastructuren, vaak werkend achter de schermen.

Een iterator is simpelweg een object dat data één element per keer oplevert. In Python wordt elk object dat de __iter__()- en __next__()-methoden implementeert een iterator genoemd.

Wanneer een object een iterator kan leveren, heet het iterable. Meeste ingebouwde containers – lijsten, tuples, strings, dictionaries – zijn iterable. De ingebouwde iter()-functie roept een object's __iter__()-methode aan om een iterator te verkrijgen.


Itereren door een iterator

Je kunt een iterator handmatig voortzetten met de next()-functie. Zodra de iterator uitgeput is, wordt StopIteration gegooid.

# definieer een lijst
my_list = [4, 7, 0, 3]
# krijg een iterator met iter()
my_iter = iter(my_list)
# itereren erdoor met next()
# Uitvoer: 4
print(next(my_iter))
# Uitvoer: 7
print(next(my_iter))
# next(obj) is hetzelfde als obj.__next__()
# Uitvoer: 0
print(my_iter.__next__())
# Uitvoer: 3
print(my_iter.__next__())
# Dit zal fout geven, geen items meer
next(my_iter)

Uitvoer

4 7 0 3 Traceback (most recent call last): File "<string>", line 24, in <module> next(my_iter) StopIteration

Een natuurlijkere manier om te itereren is met een for-lus, die de iterator-lifecycle automatisch afhandelt.

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

Hoe de for-lus met iterators werkt

De for-lus vertaalt intern naar:

for element in iterable:
    # doe iets met element

wat equivalent is aan de volgende logica:

# maak een iterator-object van dat iterable
iter_obj = iter(iterable)
# oneindige lus
while True:
    try:
        # haal het volgende item op
        element = next(iter_obj)
        # doe iets met element
    except StopIteration:
        # als StopIteration gegooid wordt, break uit lus
        break

Dit toont dat de for-lus essentieel een oneindige lus is die vertrouwt op het iterator-protocol en de StopIteration-exception om te termineren.


Eigen iterators bouwen

Een iterator vanaf nul maken is eenvoudig: implementeer __iter__() om de iterator-instantie te retourneren (vaak self) en __next__() om de volgende waarde op te leveren of StopIteration te gooien wanneer klaar.

Hieronder een voorbeeld dat opeenvolgende machten van twee oplevert tot een door de gebruiker gespecificeerde maximum-exponent.

class MachtTwee:
    """Iterator die machten van twee oplevert."""
    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

# maak een object
getallen = MachtTwee(3)
# maak een iterable van het object
i = iter(getallen)
# next gebruiken om naar volgende iterator-element te gaan
print(next(i))
print(next(i))
print(next(i))
print(next(i))
print(next(i))

Uitvoer

1 2 4 8 Traceback (most recent call last): File "/home/bsoyuj/Desktop/Untitled-1.py", line 32, in <module> print(next(i)) File "<string>", line 18, in __next__ raise StopIteration StopIteration

Een for-lus met de custom iterator is eveneens simpel:

>>> for i in MachtTwee(5):
...     print(i)
...
1
2
4
8
16
32

Python Oneindige Iterators

Iterators kunnen onbegrensd zijn. De ingebouwde iter() accepteert een callable en een sentinel-waarde: het roept de functie herhaaldelijk aan tot de geretourneerde waarde gelijk is aan de sentinel. Bijvoorbeeld:

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

Omdat int() altijd 0 retourneert, ziet iter(int, 1) nooit de sentinel, wat een oneindige iterator produceert.

Je kunt ook je eigen oneindige iterator maken, zoals één die alle oneven getallen oplevert:

class OneindigIter:
    """Oneindige iterator die opeenvolgende oneven getallen retourneert."""
    def __iter__(self):
        self.num = 1
        return self
    def __next__(self):
        num = self.num
        self.num += 2
        return num

Voorbeeldrun:

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

Bij werken met oneindige iterators, bied altijd een beëindigingsconditie om oneindige lussen te vermijden.

Iterators zijn geheugenefficiënt omdat ze items on-demand produceren. Je kunt theoretisch een onbegrensde sequentie genereren – zoals alle oneven getallen – zonder de hele set op te slaan.

Voor een simpelere manier om iterators te maken, verken Python generators using yield.

Python

  1. Python Datatypes onder de knie krijgen: Een praktische gids
  2. Python Operators onder de knie krijgen: Een uitgebreide gids
  3. Python Pass Statement onder de knie krijgen: Een praktische gids
  4. Python Functie-argumenten onder de knie krijgen: Positionele, Keyword en Default Parameters
  5. Python-dictionaries beheersen: aanmaken, manipuleren en geavanceerde technieken
  6. Python-closures uitgelegd: hoe geneste functies variabelen vangen
  7. Python datetime beheersen: praktische gids voor datums, tijden en tijdzones
  8. Python's time.sleep() onder de knie krijgen: best practices, multithreading en real-world voorbeelden
  9. Python Overzicht: Hoog-Niveau, Leesbaar, Interactief & Object-Georiënteerd
  10. Python Numbers: Immutable Numerieke Datatypes Begrijpen
  11. Python Strings Beheersen: Aanmaken, Benaderen en Manipuleren