Python中,一切皆对象,对象的集合是容器。
容器:list、tuple、dict、set
所有容器都可迭代。
迭代器 iterator
for … in …:本质就是迭代器
- 迭代器提供了一个 next(),调用后,要么得到这个容器的下一个对象,要么得到一个 StopIteration 的错误(对象迭代完了)。
- 不需要索引,next() 可以不重复不遗漏地一个一个拿到所有元素。
# 可迭代对象
li = [1,2,3]
it = iter(li)
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
print(next(it)) # StopIteration
# 相当于
for x in li:
print(x)
# 判断是否可迭代
from collections import Iterable
li = [1, 2, 3]
print(isinstance(li, Iterable)) # True
生成器
迭代器、生成器的区别
生成器:一种特殊的迭代器,懒人版的迭代器,减少内存
迭代器、生成器的区别:
- 迭代器:所有元素一次性生成,都在内存中
- 生成器:在你调用 next() 函数的时候,才会生成下一个元素。
生成器并不会像迭代器一样占用大量内存,只有在被使用的时候才会调用。而且生成器在初始化的时候,并不需要运行一次生成操作。- 迭代器是一个有限集合,生成器则可以成为一个无限集。
li = [i for i in range(100000000)] # 迭代器
li2 = (i for i in range(100000000)) # 生成器,加()
yield 实现生成器
如果一个函数中使用了 yield 关键字,则这个函数是生成器,如my_gen()
当调用该函数时,只会执行到 yield 处就暂停,返回一个生成器对象,并且保存该函数的局部信息。
当调用 next() 时,得到 yield 的返回值,并继续执行,直到再碰到 yield 停止。
from collections import Iterable
# 生成器
# 返回一个 list 中所有元素值为 data 的对应下标
def my_gen(li, data):
for i, x in enumerate(li):
if x == data:
yield i # 此时,i=0, x='a', 暂停执行
li = ['a', 'b', 'b', 'c', 'd', 'b']
g = my_gen(li, 'b')
print(type(g)) # <class 'generator'>
print(isinstance(g, Iterable)) # True
print(next(g)) # 1 # 得到 next(g) = i, 继续执行 yield 处
print(next(g)) # 2
print(next(g)) # 5
print(next(g)) # StopIteration
print(list(my_gen(li, 'b'))) # [1, 2, 5]