Python可迭代对象(Iterable)、迭代器(Iterator)和生成器(Generator)

前言:

isinstance() 验证对象类型

from typing import Iterable
from typing import Iterator
from typing import Generator

验证是否是可迭代对象:isinstance(it, Iterable)
验证是否是迭代器:isinstance(it, Iterator)
验证是否是生成器:isinstance(it, Generator)

一、可迭代对象(Iterable)

1、简单的表述是:一个类并实现了__iter__()方法,这个类就是一个可迭代(Iterable)对象

# 定义一个可迭代 对象,及实现一个__iter__()方法
class IterableTest:
    
  def __iter__(self):
    """
    此处需要定义并返回一个可以给 for 循环 正常使用的方法
    """
    pass

可改为:

class IterableTest:
    def __init__(self):
        self._str = "abcdefg"
    
    def __iter__(self):
        """
        此处需要定义并返回一个可以给 for 循环 正常使用的方法
        """
        return iter(self._str)

if __name__ == "__main__":
  it = IterableTest()  # 调用自定义的 可迭代对象
  for i in it:
    print(i)

2、常见的可迭代对象,如:listtuplesetdictstr

3、iter()函数是能够将一个 可迭代对象 转成 迭代器对象(见下述), 可通过next()取值。

a = [0, 1, 2, 3, 4, 5]
test = iter(a)
print(next(test))  # 0
print(next(test))  # 1
print(next(test))  # 2

4、注:当一个对象能够被for循环,但他并不一定是 可迭代(Iterable)对象
iter()函数可以将一个实现了__getitem__()方法的对象转成迭代器对象,也可以在for循环中使用,但是如果用isinstance()方法来检测时,它不是一个可迭代对象。

二、迭代器(Iterator)

1、一个类作为一个迭代器使用需要在类中实现两个方法 iter() 与 next()

2、实例:

# 定义一个迭代器 类
class IteratorNumbers:

    def __iter__(self):
        self.num = 0
        return self
 
    def __next__(self):
        x = self.num 
        self.num += 1
        return x


if __name__ == "__main__":
    iterator_obj= IteratorNumbers()  # 调用迭代器

    print(next(iterator_obj))
    print(next(iterator_obj))
    print(next(iterator_obj))

3、注:集合和序列对象是可迭代的但不是迭代器,而文件是属于 迭代器 对象的

print(isinstance([], Iterator)) # false
print(isinstance({}, Iterator)) # false
print(isinstance((), Iterator)) # false
print(isinstance(set(), Iterator)) # false
print(isinstance('', Iterator)) # false

# 文件类型属于迭代器
file_path = os.path.dirname(os.path.abspath(__file__))
with open(file_path +'/test.py') as file:
    print(isinstance(file, Iterator)) # true

三、生成器

1、定义生成器有两种方式:

(1)列表式生成器
(2)使用yield定义生成器函数

2、列表式生成器
列表生成器可以不需要消耗大量的内存来生成一个巨大的列表,只有在需要数据的时候才会进行计算。

def generator_test():
    x = (i for i in range(10))  # 这个左右是 (),而不能是[]
    print(x)
    print(isinstance(x, Generator))

# 结果
# <generator object generator_test.<locals>.<genexpr> at 0x000001DA33DBFCF0>
# True

3、yield方法
(1)yield的作用就相当于return, 可以通过next()或使用for循环来遍历;
(2)yield退出时保存了函数执行的位置、变量等信息;
(3)每次调用生成器的 next() 方法或使用 for 循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇到 yield 语句。

# 这个函数就是顺序地返回[0,10)的之间的自然数
def gen_num():
    for i in range(10):
        yield i

if __name__ == "__main__":
    x = gen_num()
    print(next(x))  # 0
    print(next(x))  # 1
    print(next(x))  # 2

4、生成器的优点
(1)精简代码
(2)提高性能:内存使用上,迭代器不会保存所有值,而是在运行中动态的计算出数列的各个值,并将之前运行过的的数值扔掉。

posted @ 2024-08-14 10:54  二月雪  阅读(107)  评论(0编辑  收藏  举报