Python Iterator

 

table of Contents

One, what is an iterator

Two, iterable objects

Three, create an iterator

Fourth, the application of iterators

V. Summary



One, what is an iterator

Iteration is a very powerful way to access collection elements in python . An iterator is an object that can remember the traversal position , so it will not be generated all at once like a list, but can be generated only when it is used, thus saving a lot of memory resources . The iterator object is accessed from the first element in the collection until all the elements have been accessed. There are two methods for iterators: iter() and next() methods.

Two, iterable objects

For data of types like list, tuple, str, etc., you can use the loop traversal syntax of for... in... to get the data in turn from it and use it. We call this process traversal , or iteration . The iterable objects in python are list (list), tuple (tuple), dirt (dictionary), str (string) set, etc.

mylist = [1,2,3,4,5]
mydirt = {
    "name":"张三",
    "sex":"男",
    "age":18
    }
    
mytuple = (1,2,3,4,5)
myset = {1,2,3,3,4}

for i in mylist:
    print(i)

for i in mytuple:
    print(i)

for i in myset:
    print(i)

for i,j in mydirt.items():
    print("%s:%s" % (i,j))


In addition, you can also create an iterable object : as long as the object contains the __iter__ method, then it is an iterable object , such as the following example: which defines an __iter__ method, we pass the isinstance() function And Iterable to determine whether the class1 object created by the Classmate class is an iterable object: if class1 is an Iterable (iterable object) , the result is True; otherwise, the result is False.

from collections import Iterable


class Classmate(object):
    """定义一个同学类"""

    def __init__(self):
        self.name = list()
        self.name_num = 0

    def add(self,name):
        self.name.append(name)
    
    def __iter__(self):
        pass

    
class1 =  Classmate()
class1.add("张三")
class1.add("李四")
class1.add("王五")

print("判断是否是可迭代的对象:", isinstance(class1,Iterable))

The results are as follows:

Three, create an iterator

1. As long as a class (object) contains two methods "__iter__" and "__next__" , it is called an iterator . The __iter__ method returns a special iterator object, and this iterator object automatically implements the _next__ method, and returns a value, and finally ends the iteration by throwing the exception StopIteration. Let's add the __next__ method to the previous example:

from collections import Iterable
from collections import Iterator


class Classmate(object):
    """定义一个同学类"""

    def __init__(self):
        self.name = list()
        self.name_num = 0

    def add(self,name):
        self.name.append(name)
    
    def __iter__(self):
        pass

    def __next__(self):
       pass


class1 =  Classmate()
class1.add("张三")
class1.add("李四")
class1.add("王五")

print("判断是否是可迭代的对象:", isinstance(class1,Iterable))

print("判断是否是迭代器:", isinstance(class1,Iterator))


It is still judged by the isinstance() function. If class1 is an iterator, the result returns True ; otherwise, it returns False . The results are as follows:

2. The name only iterables / iterator is not enough, having the corresponding function is considered complete. First of all, for the __iter__ method, it needs to have a function that can return an iterator object (this object can be itself (provided that it is an iterator) or other iterators); for the __next__ method, It needs to mark and return the next iterator object . The code is as follows (to prevent the iteration speed from being too fast, we add sleep to control the speed):

from collections import Iterable
from collections import Iterator
import time


class Classmate(object):
    """定义一个同学类"""

    def __init__(self):
        self.name = list()
        self.name_num = 0

    def add(self,name):
        self.name.append(name)
    
    def __iter__(self):
        return self   # 返回本身

    def __next__(self):
       
       # 记忆性返回数据
       if self.name_num < len(self.name):
           ret = self.name[self.name_num]
           self.name_num += 1
           return ret



class1 =  Classmate()
class1.add("张三")
class1.add("李四")
class1.add("王五")

print("判断是否是可迭代的对象:", isinstance(class1,Iterable))

print("判断是否是迭代器:", isinstance(class1,Iterator))

for name in class1:
    print(name)
    time.sleep(1)

The results are as follows:

It can be found that when the content that needs to be read is read , it will not stop , but will continue to return to a null value in an infinite loop . Therefore, we can add a program that throws an exception (StopIteration, used in python to mark the completion of the iteration to prevent an infinite loop) . When the required data is read, an exception will be thrown to end:

from collections import Iterable
from collections import Iterator
import time


class Classmate(object):
    """定义一个同学类"""

    def __init__(self):
        self.name = list()
        self.name_num = 0

    def add(self,name):
        self.name.append(name)
    
    def __iter__(self):
        return self   # 返回本身

    def __next__(self):
       if self.name_num < len(self.name):
           ret = self.name[self.name_num]
           self.name_num += 1
           return ret

        # 抛出异常,当循环后自动结束
       else:
           raise StopIteration


class1 =  Classmate()
class1.add("张三")
class1.add("李四")
class1.add("王五")

print("判断是否是可迭代的对象:", isinstance(class1,Iterable))

print("判断是否是迭代器:", isinstance(class1,Iterator))

for name in class1:
    print(name)
    time.sleep(1)

The results are as follows:

Fourth, the application of iterators

The core function of an iterator is to return the next value by calling the __next__ method . And this value is not read from the existing data, but generated by the program according to certain rules. This also means that we can no longer rely on an existing data set to store data , but generate it while using it, which has the advantage of saving a lot of memory space. We compare the two solutions to the following problems to further understand its application advantages:

Question : Try to write a program to realize the Fibonacci sequence (0,1,1,2,3,5,8,13,21...The latter item is always equal to the sum of the first two items):

method one:

a = 0
b = 1
myFibonacci = list()

nums = int(input("请输入需要生成Fibonacci数列项的个数:"))

i = 0
while i < nums:
    myFabonacci.append(a)
    a,b = b,a+b
    i += 1

for num in nums:
    print(num)

Method Two:

class Fibonacci(object):
    """斐波那契数列得迭代器"""
    def __init__(self,nums):
        self.nums = nums   # 传入参数,生成斐波那契数列的个数
        self.a = 0   
        self.b = 1
        self.i =0    # 用于记忆生成的个数
    def __iter__(self):
        return self

    def __next__(self):
           
       ret = self.a   # 记忆第一个数

       if self.i < self.nums:
            self.a, self.b = self.b,self.a +self.b
            self.i += 1
            return ret
       else:
           raise StopIteration   # 停止迭代

nums = int(input("请输入需要生成Fibonacci数列项的个数:"))
fobo = Fibonacci(nums)

for num in fobo:
    print(num)





If we need to generate 10 Fibonacci sequence items, the results of both operations are the same, as follows:

Although the results are the same, the actual effects are quite different . Let’s take a look at method one . It uses a while loop to immediately generate a list to store data, and then read the required data from the existing data, which requires a certain amount of memory space ; let’s look at method two , it and did not use a list, but return an iterator , in generating needed data. Looking at the above two methods, when the number of generations is small, there is not much difference between the two, but when the number of generations is 100,000, 1 million, or 10 million? The former needs to consume a lot of memory resources, while the latter only needs a little memory. This is also the difference between the range() function in python2 and the range() function in python3. The range() function of python3 adopts an iterator method and no longer depends on the existing data set, which is equivalent to xrange in python2 ()function.

5. Summary:

1. Iterable objects are not necessarily iterators.

2. The iterator must be an iterable object.

3. The container type (list tuple dict str set) is an iterable object but not an iterator.

 

Guess you like

Origin blog.csdn.net/qq_45807032/article/details/105219674