关于迭代器生成器和可迭代对象比较容易混淆,虽然在实际代码中可能清楚地知道自己要写哪一种
下面会介绍
(一)可迭代对象、迭代器、生成器常用的场景
(二)可迭代对象、迭代器、生成器概念和方法
(三)如何判断变量是可迭代对象、迭代器还是生成器
***************************************** 一 ***********************************************
理解概念可以结合常用的使用场景,这或许就是概念定义的初衷
一般我们看见的一种用法是
比如:
list = [1,2,3]
it = iter(list)
print(next(it))
在这里list就是一个可迭代对象,具有“iter”方法
it变成了迭代器,具有“next”方法,“next”方法可以依次单向取出it中的元素
这个场景算是很常见的了,记住这个场景就不难理解“可迭代对象”和“迭代器”
关于生成器,比较经典的一种是“菲波那切数列”
def fib(num):
a,b,counter = 0,1,0
while True:
if counter > num:
return
yield a
a,b = b, a+b
counter += 1
f = fib(10)
print(next(f))
fib函数的特点就是用yield关键字来标识新元素的位置。可以发现fib函数返回的f又可以调用“next”方法了,以依次单向读取元素,也就是迭代器了,生成器生成了一个迭代器(在不使用“iter”方法的情况下)
***************************************** 二 ***********************************************
下面介绍三个概念:
1、 可迭代对象
可以直接作用于for循环的对象
只要定义了iter()就是可迭代对象
例子1:
dict,list,string
2、 迭代器
是遍历元素集合的一种方法,可以记住上次读取元素的位置,并通过next方法继续读取下一个元素
是for循环实际上操作的对象
把一个类作为迭代器使用,需要实现iter,next两个
迭代器只能向前不能后退,不具有撤销性
两个基本方法:iter(), next()
例子1:
Iter(dict), iter(list), iter(string)可以直接for循环操作
例子2:
class MuNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a < 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration
# 实例化
m = MyNumbers()
m_iter = iter(m)
print(next(m_iter))
3、 生成器
一个返回迭代器的函数,只能用于迭代操作
作用之一是节省内存,它可以在循环中计算,一边生成数据一边不占内存,因为每个数据使用的是一个变量
例子1:
G = (i+a for I in list1 for a in list2)
调用方法:next(G)
例子2:
如下的斐波那契生成器函数
比较常见的一个生成器函数是斐波那契,调用的方法是多样的,参考??代码
def fib(num):
a,b,counter = 0,1,0
while True:
if counter > num:
return
yield a
a,b = b, a+b
counter += 1
f = fib(10)
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print('*******')
print(f.__next__())
print(f.__next__())
print('*******')
print([i for i in f])
运行结果是这样的,可以看见next和next函数的调用效果相同,可以使生成器函数内部的数据向前移动,导致了最终遍历的时候遍历不到,其实for循环的实际操作也是按照相同的方法向下迭代的
0
1
1
2
*******
3
5
*******
[8, 13, 21, 34, 55]
***************************************** 三 ***********************************************
用collections判断list的类型,运行效果如下:
可以看出,list是可迭代对象而不是迭代器,拥有iter()方法,没有next()方法,并且在调用了iter()方法之后就变成了迭代器。
实例化的MyNumbers具有iter方法和next方法,既是可迭代对象也是迭代器,测试结果如下:
MyNumbers类型判断.png
而且m与m_iter指向同一个对象
判断inspect判断生成器
inspect检测生成器.png
网友评论