可迭代对象
只有数学类型中有内置方法.__iter__
,称为可迭代对象
str, list, tuple, dict, set, file都是可迭代对象。
但是只有str, list, tuple可以通过索引来取值, dict, set, file可以通过迭代器来取值的
迭代器
只有数学类型中有内置方法.__next__
,称为迭代器。
只有file类型有,可迭代对象可以通过item()方法赋值给迭代器对象,此时的迭代器对象都可以使用__next__
来取值。
因此可以让dict, set, file转为迭代器对象,通过next方法来取值
- 特点:
- 提供一种统一的、不依赖与索引的取值方式,为for循环提供了依据
- 迭代器同一时间在内存中只有一个值—>更节省内存空间
- 缺点:
- 只能往后取,并且是一次性的
- 不能统计值的个数,即长度
1 | In [23]: a = {'a':1,'b':2,'c':3} |
1 | In [34]: for i in a: |
上面的for循环等同于下面的while循环1
2
3
4
5
6
7
8
9
10In [35]: b = iter(a)
In [37]: while 1:
...: try:
...: print(next(b))
...: except Exception: ##捕捉所有异常
...: break
...:
c
b
a
因此可以执行for循环,内部其实就是先把可迭代对象转为迭代器对象,在通过next方法来取值
生成器
自定义函数中带有yield
,就称为生成器。由于可以使用next方法,生成器是迭代器。
1 | def foo(): |
通过生成器next方法就可以取到x的值了
往生成器里取值
程序是不会执行生成器里面的内容,只有使用next()才会执行生成器并在执行到yield处返回值再次跳出生成器。再使用next()时会在刚刚yield处开始。
1 | def foo(): |
1 | def foo(): |
往生成器里传值
send方法可以往生成器里传值并执行下一步1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def foo():
def wrapper():
x = []
while 1:
n = yield
x.append(n)
print(x)
return wrapper
a = foo()
yield_jg = a()
yield_jg.__next__()
yield_jg.send(1) ##传值1后继续循环
yield_jg.send(2)
yield_jg.send(3)
往生成器里传值并通过yield返回值到外打印出来1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19def foo():
def wrapper():
x = []
while 1:
n = yield x #外向里传值 并返回值到外
x.append(n)
return wrapper
a = foo()
yield_jg = a()
yield_jg.__next__() ##第一次进入生成器内部
i = 0
while 1:
if i == 4:
break
k = yield_jg.send(i) ##进入生成器内部并传值
print(k)
i+=1
总结
可迭代对象
(所有数据类型)>迭代器
(遍历没有索引的数据类型)>生成器
(自定义带yield的函数)item方法
让数据类型转为迭代器next方法
让迭代器却出取出下一步的值。也可以进入生成器继续执行其内容。send方法
向生成器里传值并继续执行其内容
参考文章 https://blog.csdn.net/qq_34857250/article/details/78882422