python knowledge - iterable objects (Iterable), iterators (Iterator) and generators (Generator)

A first introduction to iterators and iterable objects 

The following data types can be directly used in for loops:
   • Collection data types:
        list, tuple, dict, set, str  (only iterable objects, not iterators)
   • Generator: (both iterable objects and iterators ) (
        generator function) with yield.
These objects that can be directly used in for loops are collectively called iterable objects: Iterable.

        You can use isinstance() to determine whether an object is an iterable object Iterable and whether it is an iterator Iterator, as shown in Example 1 below :

# 迭代器(Iterator)与可迭代对象(Iterable)
from collections import Iterable,Iterator
# isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。
print(isinstance('abc', Iterable)) # True ‘’<class 'str'>
print(isinstance([], Iterable)) # True []表示列表
print(isinstance({}, Iterable)) # True <class 'dict'>
print(isinstance((), Iterable)) # True ()表示元组
print(isinstance([], Iterator)) # False
print(isinstance({}, Iterator)) # False
print(isinstance((), Iterator)) # False
m = set('runoob') # 创建一个集合:{'b', 'n', 'o', 'r', 'u'} 集合是一个可迭代对象(Iterable),但集合不是迭代器(Iterator)
print(isinstance(m, Iterable)) # True
print(isinstance(m, Iterator)) # False

        By running the above code, we can know that the five data types of list, set, dict, tuple, and str are all iterable objects (Iterable), but they are not iterators (Iterator).

Builder

        In Python, functions using the yield keyword are called generators.
        yield
 is a keyword used to define a generator function, which is a special function that gradually produces values ​​during an iterative process rather than returning all results at once.
        Different from ordinary functions, a generator is a function that returns an iterator and can only be used for iterative operations. It is easier to understand that a generator is an iterator. When the yield
statement         is used in a generator function  , the execution of the function will be paused and  the expression following yield will be returned as the value of the current iteration. Then, each time you call the generator's  next()  method or  iterate  using a for loop, the function continues execution from where it last paused until it encounters a yield  statement again. This way, the generator function can gradually produce values ​​without having to calculate and return all results at once. Calling a generator function returns an iterator object. Here is a simple example showing the use of generator functions: (Example 2)
        

# 生成器
def countdown(n):
    while n > 0:
        yield n
        n -= 1

# 创建生成器对象
generator = countdown(5)

# 通过迭代生成器获取值
print(next(generator))  # 输出: 5
print(next(generator))  # 输出: 4
print(next(generator))  # 输出: 3

# 使用 for 循环迭代生成器
for value in generator:
    print(value)  # 输出: 2 1

        In the above example, the countdown  function is a generator function. It uses the yield statement to gradually generate reciprocal numbers from n to 1. Each time the yield statement is called, the function returns the current reciprocal value and resumes execution where it left off on the next call.
        We can step by step obtain the values ​​produced by a generator function by creating a generator object and iterating over the generator using the next() function or a for loop. In this example, we first use the next() function to get the first three reciprocal values, and then use the for loop to get the remaining two reciprocal values.
        The advantage of generator functions is that they can generate values ​​on demand, avoiding the need to generate large amounts of data at once and occupy large amounts of memory. In addition, generators can work seamlessly with other iteration tools (such as for loops) to provide a concise and efficient iteration method.
        The generator can not only use a for loop, but also use the next() function to continuously obtain the next value until a StopIteration error is finally thrown, as shown in Example 3 below .

# 生成器
def countdown(n):
    while n > 0:
        yield n
        n -= 1

# 创建生成器对象
generator = countdown(5)

# 通过迭代生成器获取值
print(next(generator))  # 输出: 5
print(next(generator))  # 输出: 4
print(next(generator))  # 输出: 3

# 使用 for 循环迭代生成器
for value in generator:
    print(value)  # 输出: 2 1
print(next(generator)) # 报错StopIteration

        The code in Example 3 adds a print(next(generator)) sentence after the basis of Example 2.  When this code is executed, the program will throw a StopIteration error. This is because the content in the iterator has been iterated before executing this code. If iteration is performed again, a StopIteration error will be reported.

        Let’s take a look at the types of generator objects, as shown in Example 4 below :

from collections import Iterable,Iterator
# 生成器
def countdown(n):
    while n > 0:
        yield n
        n -= 1

# 创建生成器对象
generator = countdown(5)

print(isinstance(generator, Iterable)) # True
print(isinstance(generator, Iterator)) # True

        Executing the code described in Example 4 , we find that the generator object is not only an iterable object (Iterable), but also an iterator (Iterator). 

Iterator 

        An object that can be continuously returned to the next value by the next() function is called an iterator Iterator object. Iterators are all Iterable objects, but Iterable objects are not necessarily iterators , such as list, dict, str, set, and tuple.

a=[1, 2, 3]
x = next(a) 
print(x)# TypeError: 'list' object is not an iterator

Iterable becomes Iterator 

        To turn Iterables such as list, dict, str, tuple, set, etc. into Iterators, you can use the iter() function, as shown in Example 5 below :

# iter()函数以及next()函数
a=[1, 2, 3] # a是可迭代对象,但不是迭代器对象
it = iter(a) #创建迭代器对象
x = next(it)
print(x) # 1
y = next(it)
print(y) # 2
z = next(it)
print(z) # 3
m = next(it)
print(m) # 报错 StopIteration

        In order to avoid reporting StopIteration, we generally consider the following changes, as shown in Example 6 below :

# 首先获得Iterator对象:
it = iter([1, 2, 3])
# 循环:
while True:
    try:
        # 获得下一个值:
        x = next(it)
        print(x) # 1 2 3
    except StopIteration:
        # 遇到StopIteration就退出循环
        break

After this change, the program will no longer report an error due to StopIteration.

Why are list, dict, tuple, str, set and other data types not iterators?

        The Iterator object represents a data stream, which can be called by the next() function and continuously returns the next data until a StopIteration error is thrown when there is no data. This data flow can be regarded as an ordered sequence, but the length of the sequence cannot be known in advance. The next data can only be calculated on demand through the next() function. Therefore, the calculation of Iterator is lazy and only returns when needed. The calculation will not be performed until the next data is received.
        Iterator can even represent an infinite data stream, but objects such as list and tuple can never store infinite data, such as all natural numbers.

The difference between iterator and iterable

(1) Iterators must be iterable objects, but iterable objects are not necessarily iterators
(2) Only iterator objects can use the next method, and they can also use for loops; iterable objects can use for loops, but they cannot use next Method
(3) Generally, you can use the iter function to convert the iterable object into an iterator object
(4) The iterable object will directly read all the contents of the incoming object into the memory, while the iterator reads one by one, only when needed data is generated when
 

Guess you like

Origin blog.csdn.net/m0_48241022/article/details/132869224