一、可迭代对象
六大标准数据类型:字符串,列表,元组,字典,集合,数值类型
可迭代对象:字符串,列表,元组,字典,集合。即:通过for...in...方式遍历的类型即为可迭代对象
定义:
1)实现了__iter__方法
2)__iter__方法方法返回了一个选代器对象
本质:
其实都是collections(容器数据类型)模块里的iterable类创建出来的实例。
查看是否为可迭代对象:
from collections.abc import Iterable #3.3-3.9版本需要加abc
print(isinstance([1, 2, 3], Iterable))>> True
二、迭代器
迭代器是访问可迭代对象的工具。其从集合的第一个元素开始访问,直到所有的元素被访问完才结束。迭代器只能往前不能后退。
两个函数
1、iter()函数--可取得可迭代对象的迭代器
2、next()函数
迭代器= iter(可迭代对象)
下个值=next(迭代器)
对迭代器调用iter()方法则返回迭代器本身 。
list = [1,2,3,4]
it = iter(list)print(it)
>> <list_iterator object at 0x000001A907BDAFD0>print(iter(it))
>> <list_iterator object at 0x000001A907BDAFD0>
功能
1)for 循环
2)逐行遍历文本文件3)列表推导式
4)元组拆包
特征
1、访问者不需要关心选代器内部结构,只需要不断执行next()方法获取下一个内容
2、不能随机访问集合中某个值,只能从头到尾顺序的读取 ---缺点
3、访问过程中不能回退,不能访问之前的值 ---缺点
4、选代器经过依次取值的循环后就耗尽,如果想再次迭代要重建选代器 --缺点易耗损性
5、适合遍历很大的数据集合,节省内存,提升速度 --应用场景
for循环工作原理
1、在内部对可迭代对象调用__iter__()方法,获取到选代器对象
2、再一次次的通过选代器对象调用__next__()方法获取选代结果
3、循环步骤2,取尽所有值,直到抛出StopIteration的异常,for循环会捕捉到异常后结束循环
演示
list = [1,2,3,4]
it = iter(list)
print(it) #输出<list_iterator object at 0x00000203602FAFD0>
print(next(it)) #输出1
print(next(it)) #输出2
print(next(it)) #输出3
print(next(it)) #输出4
print(next(it)) #抛出StopIteration异常
三、迭代器协议
概念
迭代器对象必须提供一个next方法,执行该方法要么返回迭代的下一项,要么就引起一个StopIteration异常来终止迭代(只能往后走,不能往前退)
构造迭代器
类中创建__iter__()和__next__()2个方法,__iter__()返回self对象,即可把类作为迭代器使用
class Calculate:def __iter__(self):self.number = 1return selfdef __next__(self):self.number += 1return self.numberfrom collections.abc import Iterable
cal = Calculate()
print(isinstance(cal, Iterable)) #输出Trueit = iter(cal)
print(next(it)) #输出2
print(next(it)) #输出3
print(next(it)) #输出4
四、生成器
迭代器与生成器区别
迭代器用于从数据集中取出元素;
生成器用于“凭空”生成元素,它不会一次性将所有元素全部生成,而是按需一个一个地生成,所以从头到尾都只需占用一个元素的空间。
生成器函数
只要在def中有yield关键字的 就称为 生成器。
使用yield语句返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。第一次调用完后状态挂起,下次执行时,从挂起的位置继续开始执行。
def func():yield 1yield 2yield 3return "End of function" #return返回一个值,是StopIteration的说明,而不是程序的返回值#取值方式1
fn = func()
print(next(fn))
print(next(fn))
print(next(fn))
print(next(fn)) #抛异常:StopIteration: End of function#取值方式2
for i in func():print(i)>>
1
2
3
生成器创建
只要把列表生成式中的[]改成()即可
#列表推导式
list1=[i*2 for i in range(3)] #列表推导式print(list1)
print(list1) #[0,2,4]#创建生成器表达式
list2=(i*2 for i in range(3))
print(list2) #<generator object <genexpr> at 0x000002B1B4728200>
print(next(list2))
print(next(list2))
print(next(list2))
按需生成,只占一个元素内存空间
优点
- 延迟计算,每次返回一个结果。它不会一次生成所有的结果,对于大数据量的处理,将会非常有用
- 节省内存
- 节省代码
yield与return的区别
相同点:都是返回函数执行的结果。
不同点:return在返回结果后结束函数的运行,yield让函数变成一个生成器 。
yield生成器相比return一次返回所有的结果的优势:1.反应更加迅速;2.更节省空间;3.使用更加灵活