B12_可迭代对象|迭代器|生成器详解
其他
2021-12-11 16:50:08
阅读次数: 0
可迭代对象
1. 什么是可迭代对象
- 可迭代对象,只要对象的内部实现了
__iter__()
方法,这个对象就是可迭代对象
- 可迭代可以调用
iter(obj)
,获取一个迭代器
- 可以通过
isinstance(obj,collections.abc.Iterable)
来判断是否是可迭代对象
- 如果么有实现
__iter__
方法,但是实现了__getitem__
方法,这个对象也是可迭代对象.
但是它的类型不是Iterable
类型,只是可以迭代
- 可迭代对象可以通过
for elem in iterable
的方式进行遍历
- 内置函数
iter(iterable)
可以获得迭代器对象Iterator
,然后通过next(Iterator)
,可以获取访问下一个元素
-
常见的可迭代对象
-
可迭代对象的本质
- 当要迭代一个对象的时候,系统会调用
iter(obj)
方法
- 内置的
iter(obj)
方法会做以下的事情
- 首先是检查对象是否实现了
__iter__
方法,如果实现了__iter__
方法,调用它获得一个迭代器
- 如果没有实现
__iter__
方法,但是实现了__getitem__
方法,python解释器会创建一个迭代器,尝试按照顺序(从索引0开始)获取元素
- 如果尝试失败,python会抛出
TypeError
异常
-
自定义的可迭代对象
如果没有实现__iter__()方法,但是实现了__getitem__方法,这个对象也是可以迭代的,只是它的类型和Iterable不是同类型的,但是可以使用for循环进行迭代
2. 什么是迭代器
- 迭代器是一个保存了位置状态的对象,从第一个元素开始访问,直到所有的元素被访问完结束
- 迭代器只能往前不能往后
- 迭代器必须是实现了
__iter__
方法和__next__
方法
__iter__
方法返回一个带有___next__
方法的对象,也就是迭代器本身,调用iter(obj)
的时候会被隐式调用,当然你也可以显示调用,一般不建议显式调用这种内置的魔法方法.
__next__
方法将逐一的访问容器中的元素.当访问到最后元素的下一个元素的时候,引发StopIteration
异常,调用next()
的时候,会隐式的调用__next__
方法.
- 迭代器可以通过内置函数
iter(iterable)
获取
- 判断一个对象是否是迭代器可以通过
isinstance(obj,collections.abc.Iterator)
的方式
__iter__
方法返回迭代器本身(self)
,__next__
方法返回单个元素
自定义一个迭代器,模拟range()函数
3. 生成器
- 生成器是一种特殊的迭代器,它不需要实现
__iter__
和__next__
方法
- 实现方式有两种:
生成器函数(带yield的函数)
和 生成器表达式
- 生成器可以传入数据(通过
send
),迭代器不行
- 生成器不会一次把所有的元素都加载到内存,而是在调用的时候才生成返回结果
- 可以通过for循环进行迭代(因为它也是迭代器)
- 生成器和函数的区别是,生成器有yield关键字,每次调用的时候都返回yield后面的表达式的值,
并且会记住这个生成器函数的执行位置,下次迭代的时候,从yield的下一条语句开始执行
- 通过
next(gen)
的方式可以获取生成器的下一条yield
的值,for
循环执行的时候也是一样的,在遇到
StopIteration
异常的时候结束
.send
和next()
一样,都能让生成器前进一步(遇到下一个yield后者没有报异常),但是send()能传入一个参数,这个参数是上一次yield
表达式的结果.send()
改变的是上一次yield
的表达式的结果,所以生成器第一次调用的时候,如果使用了send
,只能使用.send(None)
,因为是第一次调用,还没有yield
表达式的结果给send
后面的参数赋值接收 .send(None)
和调用一次next()
的结果和过程是一致的
-
生成器函数(带yield关键字的函数)
-
带send()的生成器函数
-
生成器表达式
- 列表推导式的
[]
改成()
就是生成器表达式
- 语法结果就是
(res for element in iterable if expression)
- 生成器表达式的结果是一个生成器对象,可以迭代和使用
next()
进行访问
4. 容器|可迭代对象|迭代器|生成器之间的关系
转载自blog.csdn.net/Fioman_GYM/article/details/120626539