首先迭代是指python中访问元素的一种方式,迭代器是一个可以记住遍历位置的对象,因此不会像列表那样一次性全部生成,而是可以等到用的时候才生成,因此节省了大量的内存资源
类似于list、tuple、str 等类型的数据可以使用for循环遍历语法从其中依次拿到数据并进行使用,我们把这个过程称为遍历,也称迭代。python中可迭代的对象有list(列表)、tuple(元组)、dirt(字典)、str(字符串)set等
除此之外还可以通过instance
来判断平常使用的字符串,列表,元组和字典等,若s是一个**Iterable(可迭代对象)**则结果返回为True
# 导入Iterable,Iterator模块
from collections.abc import Iterable,Iterator
s = "abcdefgh"
print(isinstance(s,Iterable)) # True
print(isinstance(s,Iterator)) # False
l = [1,2,3,4,5,6,7,8]
print(isinstance(s,Iterable)) # True
print(isinstance(s,Iterator)) # False
t = (1,2,3,4,5,6,7,8)
print(isinstance(s,Iterable)) # True
print(isinstance(s,Iterator)) # False
只是名义上的 可迭代对象/迭代器 还不够,具有相应的功能才算是完整。首先,对于__iter__
方法,它需要具有一个可以返回一个迭代器对象的功能(这个对象可以是自己(前提是本身就是一个迭代器),也可以是其它迭代器);对于__next__
方法,它是用于获取迭代器(Iterator)
中的下一个元素。它的基本语法是:
next(iterator[, default])
iterator
是要获取下一个元素的迭代器对象。default
是一个可选参数,表示在迭代器耗尽时返回的默认值。如果不提供 default
参数且迭代器耗尽,则会引发 StopIteration
异常。以下是一些next()
方法的用例
# 创建一个列表和迭代器对象
my_list = [1, 2, 3, 4, 5]
my_iterator = iter(my_list)
# 逐个获取迭代器中的元素
print(next(my_iterator)) # 输出: 1
print(next(my_iterator)) # 输出: 2
print(next(my_iterator)) # 输出: 3
# 使用默认值处理迭代器耗尽的情况
print(next(my_iterator, "End")) # 输出: 4
print(next(my_iterator, "End")) # 输出: 5
print(next(my_iterator, "End")) # 输出: End
next()
方法在循环中经常被用来逐个处理迭代器中的元素,直到迭代器耗尽或满足某个条件。这种方式可以避免一次性加载整个序列到内存中,节省资源并提高效率
生成器(generator)也是一种迭代器,在每次迭代时返回一个值,直到抛出 StopIteration异常。它有两种构造方式:
和列表推导式的定义类似,生成器表达式使用 () 而不是 [] ,比如:
print((i for i in range(5)))
# <generator object <genexpr> at 0x00000235C67B9700>
nums = (i for i in range(5))
for num in nums:
print(num)
# 0 1 2 3 4
print(isinstance(nums, Iterable)) # True 表示nums属于可迭代对象
print(isinstance(nums, Iterator)) # True 表示nums属于迭代器
含有 yield
关键字的函数,调用该函数时会返回一个生成器。生成器对象可以通过调用其方法(例如 next()
)来逐步执行函数体中的代码,每次调用会产生一个值,并在遇到 yield
语句时暂停执行。
def my_generator():
for i in range(10):
print(i)
if i > 7:
yield '大于7'
# 使用生成器函数
gen = my_generator()
for i in gen:
print(i)
# 0 1 2 3 4 5 6 7 8大于7 9大于7
# __next__方法
gen = my_generator()
print(next(gen))
print(next(gen))
print(next(gen))
# 0 1 2 3 4 5 6 7 8大于7 9大于7 超过最大值然后报错
# print(next(gen))
# ^^^^^^^^^
# StopIteration
调用该函数的时候不会立即执行代码,而是返回了一个生成器对象;
当使用 next() (在 for 循环中会自动调用 next() ) 作用于返回的生成器对象时,函数 开始执行,在遇到 yield 的时候会『暂停』,并返回当前的迭代值;
当再次使用 next() 的时候,函数会从原来『暂停』的地方继续执行,直到遇到 yield语 句,如果没有 yield 语句,则抛出异常
简而言之,就是 next 使函数执行, yield 使函数暂停
当我们使用 send(value)
方法发送一个值到生成器时,该值会成为生成器函数中对应 yield
表达式的结果,并且生成器会从暂停的位置继续执行
def my_generator():
x = yield 'Ready' # 第一次调用 send() 方法将被忽略
yield f'Received: {x}'
gen = my_generator()
print(next(gen)) # 输出: 'Ready'
print(gen.send('Hello')) # 输出: 'Received: Hello'
我们可以使用 close() 方法来关闭一个生成器。生成器被关闭后,再次调用 next() 方法,不管能否遇到 yield 关键字,都会抛出 StopIteration 异常
def my_generator():
for i in range(10):
print(i)
if i > 7:
yield '大于7'
# 使用生成器函数
gen = my_generator()
gen.close() # 关闭生成器
print(next(gen))
# StopIteration 报错