一、三者在代码上的特征
1.有__iter__方法的对象就是可迭代类(对象)
2.有__iter__方法,__next()方法的对象就是迭代器
3.生成器 == 函数+yield
生成器属于迭代器, 迭代器是特殊的可迭代对象
二、各自的执行过程
1.可迭代对象执行过程
1.先调用iter()函数: iter(iterable) -> iterator : 函数传入一个可迭代对象(iterable),返回迭代器(iterator);
内部是通过可迭代对象(iterable)的__iter__ ()取得迭代器(iterator)
2.再调用next()函数: next(iterator)->Return the next item from the iterator : 函数传入一个迭代器(iterator),返回迭代器指向的下一个值;
内部是通过迭代器(iterator)的__next__ ()取得下一个值(iitem)
代码如下:
# 定义一个可迭代对象,如列表
list1 = [1, 2, 3, 4, ] # 通过iter()生成一个迭代器
list_iterator = iter(list1) # 通过next()取得迭代器指向的下一个元素,默认从第一个开始
print("第1个迭代出的元素:",next(list_iterator))
print("第2个迭代出的元素:",next(list_iterator))
print("第3个迭代出的元素:",next(list_iterator))
print("第4个迭代出的元素:",next(list_iterator)) 结果如下:
第1个迭代出的元素: 1
第2个迭代出的元素: 2
第3个迭代出的元素: 3
第4个迭代出的元素: 4 进程已结束,退出代码 0
补充:
列表元祖等是可迭代对象,但不是可迭代器,虽然可以调用内部__iter__方法,返回的是一个迭代器,但不是自己的本身(本身就不是生成器),所以不能直接所以不能直接调用next()返回迭代器指向的下一个值,必须先调用iter()方法
2.yield实现生成器的执行过程
1. 假如函数中有yield,则不再是函数,而是生成器
2. yield 会产生一个断点,暂停函数 ,挂起函数, 且保存当前状态
3. 假如yield后面紧接着一个数据,就会把数据返回,
作为next()函数或者for ...in...迭代出的下一个值
4. 可以通过next()唤醒生成器,让生成器从断点处继续执行
代码如下:
def fibo(n):
"""使用yield实现生成器求斐波那契数列"""
count = 0 # 记录当前迭代的位置,初始值为0
num1, num2 = 0, 1 # 初始化数列的前两位值 0,1
while count < n:
yield num1
num1, num2 = num2, num1 + num2
count += 1 # 自加一,迭代器指针指向下一个位置 # 创建生成器,生成器默认是沉睡的,假如是第一次唤醒生成器(函数),则从生成器(函数)的起始位置开始运行
gen = fibo(10) # 使用next()迭代
print("返回的值:", next(gen))
print("返回的值:", next(gen))
print("返回的值:", next(gen))
print("返回的值:", next(gen))
print("返回的值:", next(gen))
print("返回的值:", next(gen))
print("返回的值:", next(gen))
print("返回的值:", next(gen))
print("返回的值:", next(gen))
print("返回的值:", next(gen)) 结果如下:
返回的值: 0
返回的值: 1
返回的值: 1
返回的值: 2
返回的值: 3
返回的值: 5
返回的值: 8
返回的值: 13
返回的值: 21
返回的值: 34 进程已结束,退出代码 1
三、总结三者拿到迭代出的数据的方法如下:
生成器 : 可使用next()/send() 拿到数据
迭代器: 可使用next() 拿到数据
可迭代对象(只是可迭代对象): 可使用iter() +next() 拿到数据
如果你和我有共同爱好,我们可以加个好友一起交流!