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、常见的可迭代对象,如:list
、tuple
、set
、dict
、str
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)提高性能:内存使用上,迭代器不会保存所有值,而是在运行中动态的计算出数列的各个值,并将之前运行过的的数值扔掉。