Introduction and use of Python iterator mode

1. Introduction to Python iterator mode

The Python iterator pattern is a design pattern that provides a uniform interface for accessing elements in a container object without exposing the details of the container's internals.

In Python, an iterator is an object that implements the __next__() method, which returns the next element in the container and throws a StopIteration exception when the container ends. By using the iterator pattern, we can easily iterate over sequences, aggregates, and other iterable objects.

advantage:

  1. Simplifies the traversal process without paying attention to the underlying implementation;
  2. Reduced coupling between data structures and traversal algorithms;
  3. Support lazy loading to save memory resources.

shortcoming:

  1. The iterator can only traverse the data in the container and cannot modify the data;
  2. Iterators can only traverse in one direction, not in reverse.

Application scenario: When you need to traverse sequences or aggregates (such as lists, tuples, dictionaries, etc.), you can use the iterator mode.

How to use: The built-in iter() function in Python returns an iterator object, which accepts an iterable object as a parameter and implements the __iter__() method. Calling the __next__() method of an iterator can traverse all elements of the container object.

Use in application development: The iterator mode can be used for memory optimization for processing large amounts of data, and realizes on-demand loading of data. In Python, generator functions are a common example of using the iterator pattern.

Second, the use of iterator mode

working principle:

The core idea of ​​the iterator pattern is to separate container objects from traversal algorithms so that they can vary independently. The container object implements the __iter__() method, which returns an iterator object, and the iterator object implements the __next__() method, which is used to traverse the elements in the container. In this way, we can use different traversal algorithms to traverse the same container object without modifying the container.

Example 1: Realize the function of calculating the number of failed students

The following is a simple example to illustrate the working principle and usage of the Python iterator mode.

Suppose we have a list of students and need to count the number of students who failed a grade. We can use the iterator pattern to achieve this:

A Student class is defined, which has a name and a grade property. We also define a StudentList class that can add student objects and return an iterator object. The iterator object is an instance of the StudentIterator class, which implements the __next__() method and can traverse all the students in the student list.

Finally, we define a FailingStudentsCounter class that uses the StudentList object to count the number of failing students. We get the iterator object by calling the get_iterator() method of the StudentList object, and use a while loop and a try-except statement to iterate through all the students. When the iterator reaches the end of the list, a StopIteration exception is thrown to indicate the end of the iteration.

# 定义类。 定义学生属性:名字、成绩
class Student():
    def __init__(self, name, score):
        self.name = name
        self.score = score

# 定义列表。定义学生列表
class StudentList():
    def __init__(self):
        self.students = []

    def add_student(self, student):
        self.students.append(student)

    def get_interator(self): # 获取迭代器
        return StudentIterator(self.students)

# 定义迭代器。
class StudentIterator():
    def __init__(self, students):
        self.students = students
        self.index = 0

    def __next__(self):
        if self.index >= len(self.students):
            raise StopIteration
        student = self.students[self.index]
        self.index += 1
        return student

# 定义成绩不及格学生类
class FailingStudentCounter():
    def count_failing_students(self, student_list):
        count = 0
        iterator = student_list.get_interator()
        while True:
            try:
                student = next(iterator)
                if student.score < 60:
                    count += 1
            except StopIteration:
                break
        return count

# 创建实例
stu1 = Student("name1", 80)
stu2 = Student("name2",55)
stu3 = Student("name3", 100)

student_list = StudentList()
student_list.add_student(stu1)
student_list.add_student(stu2)
student_list.add_student(stu3)

counter = FailingStudentCounter()
count = counter.count_failing_students(student_list)

print(count)

operation result:

1

The final output is "Number of failing students: 1", indicating that there is one failing student. We can see that the iterator pattern can simplify the traversal process, reduce the coupling between the data structure and the traversal algorithm, and thus improve the readability and reusability of the code.

Example 2: Implement the function of traversing the list

Here is a simple example showing how to use the iterator pattern to iterate over a list:

class MyInterator():
    def __init__(self, lst):
        self.lst = lst
        self.current = 0

    def __iter__(self): # 返回迭代器对象本身
        print("返回迭代器对象本身")
        return self

    def __next__(self): # 定义遍历逻辑
        print("遍历数据")
        if self.current == len(self.lst):
            print(f"当前第 {self.current} 个数据,停止遍历")
            raise StopIteration
        else:
            result = self.lst[self.current]
            self.current += 1
            return result

# 创建实例

my_lst = [11,3,5,0,9,2]
my_inter = MyInterator(my_lst)
for i in my_inter:
    print(i)

# 相当于:
for i in my_lst:
    print(i)

operation result:

Return the iterator object itself
Traversing data
11
Traversing data
3
Traversing data
5
Traversing data
0
Traversing data
9
Traversing data
2
Traversing data
The current sixth data, stop traversing
11
3
5
0
9
2

In this example, we first define a MyIterator class that implements the __iter__() and __next__() methods. The iter () method returns the iterator object itself, so that we can use tools such as for loops to traverse it. The __next__() method defines the traversal logic of the MyIterator class, checks whether the current position is out of bounds, returns the element at the current position if it is not out of bounds, and moves the iterator pointer forward.

We then use the my_lst list to initialize the MyIterator object my_iter and use a for loop to iterate over it. During the traversal process, Python will automatically call the __next__() method of the my_iter object to get the next element until the traversal ends.

It should be noted that in Python, the list itself is an iterable object, and we can directly use the for loop to traverse a list.

Therefore, in actual development, we can choose to use the iteration method of the list itself or customize an iterator class to implement the traversal function according to our needs.

Example 3: Implement the function of traversing the dictionary

Here is a simple example showing how to iterate over the keys and values ​​of a dictionary using the iterator pattern:

class MyInterator():
    def __init__(self, dic):
        self.current = 0
        self.keys = list(dic.keys())
        self.values = list(dic.values())

    def __iter__(self): # 返回迭代器对象本身
        print("返回迭代器对象本身")
        return self

    def __next__(self): # 定义遍历逻辑
        if self.current == len(self.keys):
            print(f"当前第 {self.current} 个数据,停止遍历")
            raise StopIteration
        else:
            key_result = self.keys[self.current]
            value_result = self.values[self.current]
            self.current += 1
            return key_result, value_result

# 创建实例

my_dct = {"a":1, "b":2, "c":3}
my_iter = MyInterator(my_dct)
for key,value in my_iter:
    print(key, value)


# 相当于:
for key in my_dct:
    print(key, my_dct[key])

operation result:

Return the iterator object itself
a 1
b 2
c 3
the current third data, stop traversing
a 1
b 2
c 3

In this example, we also define a MyIterator class whose constructor initializes a list of keys and values, and returns both keys and values ​​in the __next__() method. During the traversal process, we use the for loop to traverse the MyIterator object, and store the returned key and value in the key and value respectively for output.

Therefore, we can use the iterator mode to implement the function of traversing the dictionary in order to process the keys and values ​​in the dictionary more flexibly. It should be noted that in Python 3, the dictionary itself can already return the iterator object of the key-value pair tuple through the items() method, so we can also directly use the for loop to traverse a dictionary.

Therefore, in actual development, we can choose to use the dictionary's own iteration method or customize an iterator class to implement the traversal function according to our needs.

Guess you like

Origin blog.csdn.net/songpeiying/article/details/131979414