迭代器是为了给迭代对象进行迭代使用的。迭代也就是遍历,可以从头到尾的遍历所有的元素。列表、集合、元组、字典、字符串、都是可迭代对象。如果一个对象拥有_iter方法,其是可迭代对象。
惰性计算(Lazy Evaluation):生成器使用惰性计算的方式逐个生成值。它们不会一次性生成所有值,而是按需生成,节省了内存和计算资源。这对于处理大型数据集或无限序列特别有用。
延迟执行(Lazy Execution):生成器的执行是逐步的,只在需要时才会执行代码。这种延迟执行的特性使得生成器非常适合处理耗时的操作,避免了一次性计算所有结果。
迭代器协议支持:生成器自动实现了迭代器协议,因此它们可以被 for
循环等迭代工具直接使用。这使得生成器可以方便地进行迭代遍历,无需额外的代码。
内存效率:生成器不需要存储所有生成的值,而是在需要时按需生成。这使得生成器非常适合处理大型或无限序列,因为它们节省了内存资源。
状态维护:生成器函数可以维护局部变量和状态,通过 yield
语句可以保存函数的执行状态,并在下一次调用时恢复执行。这使得生成器可以实现复杂的迭代逻辑、状态机和协程等。
数据流处理:生成器可以用于处理连续的数据流,逐个处理数据并生成结果。这对于处理实时数据或流式数据非常有用,可以逐步处理数据而无需等待所有数据到达。
管道和链式操作:生成器可以通过管道和链式操作组合在一起。一个生成器的输出可以作为另一个生成器的输入,从而实现数据流的处理和转换。
总的来说,生成器提供了一种高效、灵活和内存友好的方式来处理迭代和序列生成。它们可以用于处理大数据集、实现延迟计算、处理数据流、实现协程等各种场景。通过生成器,可以以优雅而高效的方式处理迭代逻辑,减少内存占用,并提高代码的可读性和可维护性。
__iter__()
方法:返回迭代器对象自身。__next__()
方法:返回迭代器的下一个元素,如果没有元素可供返回,则抛出 StopIteration
异常。迭代器对象可以通过调用内置的 iter()
函数来获取,它可以应用于可迭代对象(如列表、元组、字符串等)或自定义的实现了 __iter__()
方法的对象。
介绍:
用法:
iter(iterable)
参数介绍:
iterable
:可迭代的数据类型举例:
iter([1, 2, 3])
返回值:
< list_ iterator at 0x4f3aee0>
next(iterator)
iterator
:迭代器对象iter_ obj = iter([1,2,3])
next(iter_obj)
1, 2 ,3
StopIteration
yield
yield
是一个关键字,用于定义生成器函数(Generator Function)yield
语句来定义生成器的每个值,并在生成器中暂停和恢复执行。def my_generator():
# 生成器函数的逻辑
yield value1
yield value2
# ...
在生成器函数中,每个 yield
语句都会将一个值生成给调用者,并且函数的执行会在此处暂停。调用者可以通过迭代生成器对象来获取生成器函数产生的值。每次迭代,生成器函数会从上一次暂停的位置恢复执行,并生成下一个值。
以下是一个简单的生成器函数示例,生成斐波那契数列的前n个数字:
def fibonacci(n):
a, b = 0, 1
count = 0
while count < n:
yield a
a, b = b, a + b
count += 1
# 使用生成器函数生成斐波那契数列的前10个数字
fib_gen = fibonacci(10)
for num in fib_gen:
print(num)
生成器函数 fibonacci
使用 yield
语句生成每个斐波那契数列的数字。在每次迭代中,生成器函数会在 yield
处暂停,并返回生成的值。在 for
循环中,我们迭代生成器对象 fib_gen
,每次迭代都会从上一次暂停的位置恢复执行,并生成下一个斐波那契数。
生成器表达式可以直接生成一个生成器对象,而不需要定义生成器函数。
总结起来,yield
关键字用于定义生成器函数中,它允许逐步生成值的方式来创建生成器。通过 yield
,可以在生成器函数中暂停和恢复执行,并向调用者提供生成的值。这种逐步生成值的方式在处理大量数据或需要延迟计算的情况下非常有用。
In [27]: def test():
for i in range(10):
......print(i)
......yield i
In [28]: res = test()
In [29]: next(res)
0ut[29]: 0
In [30]:res=(i for i in [1,2,3])
In [31]: next(res)
Out [31] : 1
In [32]:res=(i for i in [1,2,3])
In [33]: for item in res:
...: print ( item)
1
2
3
PS: 迭代器每一次使用会将其放到内存中,将数据被读取后,内存的数据会被释放,所以当完整读取一个迭代器后,这个迭代器中的内存数据就已经空了,再次执行就拿不到数据了。
#!/user/bin/env python
# -*- coding: utf-8 -*-
iter_obj = iter((1, 2, 3))
def _next(iter_obj):
try:
return next(iter_obj)
except StopIteration:
return None
# print(_next(iter_obj))
# print(_next(iter_obj))
# print(_next(iter_obj))
# print(_next(iter_obj)) # 当迭代器中数据被调用完后,将不再被调用
for i in iter_obj:
print(i)
print('========')
def make_iter():
for i in range(10):
yield i
iter_obj = make_iter()
for i in iter_obj:
print(i)
print('---------')
"""
迭代器每一次使用会将其放到内存中,
将数据被读取后,内存的数据会被释放,
所以当完整读取一个迭代器后,这个迭代器
中的内存数据就已经空了,再次执行就拿不
到数据了
"""
for i in iter_obj:
print(i)
iter_obj = (i for i in range(5))
for i in iter_obj:
print(i)
print('========')
for i in iter_obj:
print(i)
1
2
3
========
0
1
2
3
4
5
6
7
8
9
---------
0
1
2
3
4
========
Process finished with exit code 0