Python Iterators (__iter__ και __next__): Πώς να το χρησιμοποιήσετε και γιατί;

Οι επαναληπτές είναι αντικείμενα που μπορούν να επαναληφθούν. Σε αυτό το σεμινάριο, θα μάθετε πώς λειτουργεί ο επαναληπτής και πώς μπορείτε να δημιουργήσετε το δικό σας επαναληπτικό χρησιμοποιώντας μεθόδους __iter__ και __next__.

Βίντεο: Python Iterators

Επαναληπτές στο Python

Οι επαναληπτές είναι παντού στο Python. Εφαρμόζονται κομψά μέσα σε forβρόχους, αντιλήψεις, γεννήτριες κ.λπ. αλλά κρύβονται σε απλή θέα.

Το Iterator in Python είναι απλά ένα αντικείμενο στο οποίο μπορεί να γίνει επανάληψη. Ένα αντικείμενο που θα επιστρέφει δεδομένα, ένα στοιχείο κάθε φορά.

Από τεχνικής απόψεως, ένα αντικείμενο επανάληψης Python πρέπει να εφαρμόζει δύο ειδικές μεθόδους __iter__()και __next__(), το οποίο ονομάζεται συλλογικά το πρωτόκολλο επανάληψης .

Ένα αντικείμενο ονομάζεται επαναληπτικό εάν μπορούμε να πάρουμε έναν επαναληπτικό από αυτό. Τα περισσότερα ενσωματωμένα κοντέινερ στην Python όπως: list, tuple, string κ.λπ. είναι επαναλαμβανόμενα.

Η iter()συνάρτηση (η οποία με τη σειρά της καλεί τη __iter__()μέθοδο) επιστρέφει έναν επαναληπτικό από αυτούς.

Επανάληψη μέσω ενός επαναλήπτη

Χρησιμοποιούμε τη next()συνάρτηση για να επαναλάβουμε με μη αυτόματο τρόπο όλα τα στοιχεία ενός επαναληπτικού. Όταν φτάσουμε στο τέλος και δεν υπάρχουν άλλα δεδομένα που θα επιστραφούν, θα αυξήσει την StopIterationεξαίρεση. Ακολουθεί ένα παράδειγμα.

 # 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)

Παραγωγή

 4 7 0 3 Traceback (τελευταία κλήση τελευταία): Αρχείο ", γραμμή 24, στο επόμενο (my_iter) StopIteration

Ένας πιο κομψός τρόπος αυτόματης επανάληψης είναι με τη χρήση του βρόχου για. Χρησιμοποιώντας αυτό, μπορούμε να επαναλάβουμε κάθε αντικείμενο που μπορεί να επιστρέψει έναν επαναληπτικό, για παράδειγμα λίστα, συμβολοσειρά, αρχείο κ.λπ.

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

Εργασία για βρόχο για Iterators

Όπως βλέπουμε στο παραπάνω παράδειγμα, ο forβρόχος μπόρεσε να επαναλάβει αυτόματα τη λίστα.

Στην πραγματικότητα ο forβρόχος μπορεί να επαναληφθεί σε οποιοδήποτε επαναλαμβανόμενο. Ας ρίξουμε μια πιο προσεκτική ματιά στο πώς εφαρμόζεται ο forβρόχος στην Python.

 for element in iterable: # do something with element

Στην πραγματικότητα εφαρμόζεται ως.

 # 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

Έτσι εσωτερικά, ο forβρόχος δημιουργεί ένα αντικείμενο επανάληψης, iter_objκαλώντας iter()το επαναληπτικό.

Κατά ειρωνικό τρόπο, αυτός ο forβρόχος είναι στην πραγματικότητα ένας άπειρος βρόχος.

Μέσα στο βρόχο, καλεί next()να πάρει το επόμενο στοιχείο και εκτελεί το σώμα του forβρόχου με αυτήν την τιμή. Μετά από όλα τα είδη εξάτμισης, StopIterationανυψώνεται το οποίο έχει παγιδευτεί εσωτερικά και τελειώνει ο βρόχος Σημειώστε ότι θα περάσει οποιαδήποτε άλλη εξαίρεση.

Δημιουργία προσαρμοσμένων επαναληπτών

Η κατασκευή επαναληπτικού από το μηδέν είναι εύκολη στο Python. Απλώς πρέπει να εφαρμόσουμε __iter__()και τις __next__()μεθόδους.

Η __iter__()μέθοδος επιστρέφει το ίδιο το αντικείμενο επαναληπτικού. Εάν απαιτείται, μπορεί να πραγματοποιηθεί κάποια προετοιμασία.

Η __next__()μέθοδος πρέπει να επιστρέψει το επόμενο στοιχείο στη σειρά. Όταν φτάσετε στο τέλος, και σε επόμενες κλήσεις, πρέπει να αυξηθεί StopIteration.

Εδώ, παρουσιάζουμε ένα παράδειγμα που θα μας δώσει την επόμενη δύναμη των 2 σε κάθε επανάληψη. Ο εκθέτης ισχύος ξεκινά από το μηδέν έως τον αριθμό του συνόλου χρήστη.

If you do not have any idea about object-oriented programming, visit 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))

Output

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

We can also use a for loop to iterate over our iterator class.

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

Python Infinite Iterators

It is not necessary that the item in an iterator object has to be exhausted. There can be infinite iterators (which never ends). We must be careful when handling such iterators.

Here is a simple example to demonstrate infinite iterators.

The built-in function iter() function can be called with two arguments where the first argument must be a callable object (function) and second is the sentinel. The iterator calls this function until the returned value is equal to the sentinel.

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

We can see that the int() function always returns 0. So passing it as iter(int,1) will return an iterator that calls int() until the returned value equals 1. This never happens and we get an infinite iterator.

We can also build our own infinite iterators. The following iterator will, theoretically, return all the odd numbers.

 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

A sample run would be as follows.

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

And so on…

Be careful to include a terminating condition, when iterating over these types of infinite iterators.

Το πλεονέκτημα της χρήσης επαναληπτών είναι ότι εξοικονομούν πόρους. Όπως φαίνεται παραπάνω, θα μπορούσαμε να πάρουμε όλους τους περίεργους αριθμούς χωρίς να αποθηκεύσουμε ολόκληρο το σύστημα αριθμών στη μνήμη. Μπορούμε να έχουμε άπειρα αντικείμενα (θεωρητικά) στην πεπερασμένη μνήμη.

Υπάρχει ένας ευκολότερος τρόπος για τη δημιουργία επαναληπτικών στο Python. Για να μάθετε περισσότερα επισκεφτείτε: Γεννήτριες Python χρησιμοποιώντας απόδοση.

ενδιαφέροντα άρθρα...