for loop and iterator
In Python, the for loop is a commonly used iterative structure for traversing the elements in an iterable object
. An iterator is a special object that implements the iteration protocol, allowing elements to be accessed one by one in a certain order.
There is a close relationship between for loops and iterators. In fact, for loops work based on iterators. When using a for loop to traverse an iterable object, Python will automatically create an iterator object internally, and use the iterator to fetch elements one by one until all elements have been visited.
The thing after in in the for loop must be an iterable, that is, it must be an iterable object.
Here is an example that demonstrates the relationship between for loops and iterators:
fruits = ['apple', 'banana', 'orange'] # Use a for loop to iterate through the list elements for fruit in fruits: print(fruit) # The above code is equivalent to the following iterator method iterator = iter(fruits) # Create an iterator object while True: try: fruit = next(iterator) # get the next element print(fruit) except StopIteration: break
In the above example, we first use the for loop to traverse the elements in the list fruits
and print out the name of each fruit. Then, we manually created an iterator object iterator
, and used the next()
function to get the elements one by one until a StopIteration
exception was encountered, indicating that All elements have been visited.
As you can see, using the for loop can simplify the iteration process, without explicitly creating an iterator object and handling StopIteration
exceptions. Many of Python’s built-in objects (such as lists, tuples, dictionaries, etc.) are iterable, so they can be used directly in for loops.
List
lst = [1, 2, 3] for i in lst: print(i)
dictionary
d = {<!-- -->"a": 1, "b": 2} for i in d: print(i)
File operations
with open(my.txt, "r") as f: for i in f: print(i)
In addition to the built-in iterable objects, you can also customize the iterator class to implement your own iteration logic. In this way, you can use a custom iterator in a for loop to traverse a specific data structure or implement a specific iteration behavior.
The core behind for loop is
iterator
anditerable object
.
Iterators and iterable objects
https://docs.python.org/3/glossary.html
In Python, iterables and iterators are two related but different concepts.
Iterable
refers to an object that implements the __iter__()
method, or implements the __getitem__()
method and can be accessed in order Object. Both of these are to ensure that it can return an iterator
under the action of the iter function. Iterable objects can be iterated, that is, they can be used in for loops. Common iterable objects include lists, tuples, strings, dictionaries, sets, etc.
Iterator
is a special object that implements the iteration protocol and has __iter__()
and __next__()
methods. The iterator is used to return the elements in the iterable object one by one. Each time the __next__()
method is called, the next element will be returned. If there are no more elements, a StopIteration
exception will be raised. Iterator objects can also record the iteration state during iteration.
Whenever a for loop is used to traverse an iterable object, Python will automatically create an iterator object internally, and call its __next__()
method to obtain elements one by one. Therefore, it can be said that for loops work based on iterators.
Here is an example that demonstrates the concept of iterable objects and iterators:
fruits = ['apple', 'banana', 'orange'] # fruits are iterable objects that can be used in for loops for fruit in fruits: print(fruit) # create iterator object iterator = iter(fruits) # Call the iterator's __next__() method to get the next element print(next(iterator)) # output: 'apple' print(next(iterator)) # output: 'banana' print(next(iterator)) # Output: 'orange' print(next(iterator)) # raise StopIteration exception
In the above example, fruits
is an iterable object, we can use it directly in the for loop to traverse the elements. At the same time, we can also use the iter()
function to manually convert the iterable object into an iterator object, and use the next()
function to get elements one by one. When all elements have been visited, continuing to call the next()
function will cause a StopIteration
exception.
It should be noted that the iterator is a one-time object, that is, during the iteration process, once the iterator returns all elements, it will be exhausted and cannot be used again. If you want to re-traverse the iterable object, you need to recreate the iterator object.
- An iterable is more like a data saver, a container, which can have no state, and it doesn’t know where your iterator is at all. It needs to be able to generate an iterator.
- The iterator must be stateful, but it does not need to implement a container. Of course, it must know internally what data it represents in the iterable. The iterator must have the method
__next__
. This method guarantees that it can return the next iterable when it is acted upon by next.
Customize an iterable object and the corresponding iterator-linked list
#! -*-conding=: UTF-8 -*- # 2023/5/22 18:43 class NodeIter: def __init__(self, node): self.curr_node = node def __next__(self): if self. curr_node is None: raise StopIteration node, self.curr_node = self.curr_node, self.curr_node.next return node class Node: def __init__(self, name): self.name = name self. next = None def __iter__(self): return NodeIter(self) node1 = Node("node1") node2 = Node("node2") node3 = Node("node3") node1.next = node2 node2.next = node3 if __name__ == '__main__': for node in node1: print(node.name)
If we want to use the linked list in the for loop, then we have to turn the linked list into an iterable by ourselves.
This code demonstrates how to customize an iterable object and the corresponding iterator.
First, we define a Node
class, representing a node, each node has a name and a reference to the next node. The Node
class implements the __iter__()
method, which returns an iterator object.
Then, we define a NodeIter
class as an iterator, which receives a node object as a parameter, and initializes the current node in the __init__()
method. The NodeIter
class implements the __next__()
method, which is used to return the next node. Each time the __next__()
method is called, it returns the current node as a result and updates the current node to the next node. When there are no more nodes, a StopIteration
exception is thrown.
Finally, under the if __name__ == '__main__':
condition, we use custom iterable objects and iterators for traversal. Through the syntax of for node in node1:
, the __iter__()
method of the node1
object will be called automatically to obtain the iterator, and obtained one by one through the iterator node, and print the name of the node.
Running the above code, the output is:
node1 node2 node3
This example shows how to customize iterable objects and iterators, and use them in for loops to implement custom iteration logic.
If you like this article, please follow it, or pay attention to my official account “Haige python“. I will continue to share high-quality Python articles and other related content.