迭代器
迭代器(Iterator)是一个可以记住遍历的位置的对象,该对象包含值的可计数数字,在Python当中:迭代器是实现迭代器协议的对象,它包含方法__iter__() 和 __next__()
__iter__()方法
- 作用:返回迭代器对象本身
__next__()方法
- 作用:返回迭代器的下一个元素,如果没有元素了则就会触发StopIteration异常
可迭代对象
如果一个对象/类中,有__iter__()方法并且返回一个迭代器对象,则我们称以这个对象/类创建的对象为可迭代对象。
列表、元组、字典、集合都可以是可迭代的对象。它们都是可迭代的容器,可以从中获取到迭代器
可以通过dir函数可以列出对象方法:
My_list = [1, 2, 3, 4, 5]
a = dir(My_list)
print(a)
实例
My_list = [1, 2, 3, 4, 5]
it = iter(My_list) # 创建迭代器的对象
print(next(it)) # 输出迭代器的下一个对象
print(next(it))
遍历可迭代对象
我们可以使用for循环来遍历可迭代的对象
my_count = ("one", "tow", "three")
for i in my_count:
print(i)
创建迭代器
要把对象或者类创建成为迭代器,必须为对象实现__iter__() 方法 和 __next__() 方法
在面向对象编程中类都有一个构造函数,Python的构造函数为__init__(),它会在对象进行初始化的时候执行。
__iter__()方法返回一个特殊的迭代器对象,这个迭代器对象实现了__next__()方法,可以执行操作,但必须返回迭代器对象本身
__next__()方法会返回下一个迭代器对象
实例
class AddOneIterator:
def __init__(self, start=0):
self.current = start # 初始化起始值
def __iter__(self):
return self
def __next__(self):
self.current += 1
return self.current
# 创建一个加1的迭代器,从0开始
iterator = AddOneIterator()
# 使用迭代器获取前几个加1后的值
print(next(iterator)) # 输出:1
print(next(iterator)) # 输出:2
print(next(iterator)) # 输出:3
print(next(iterator)) # 输出:4
StopIteration
当我们执行上面代码的时候,可以发现如果有足够的next,或者我们在for循环里面使用,则上面的实例将会一直执行下去。
所以为了防止迭代永远进行,我们可以使用 StopIteration 语句
实例:在next()方法中,我们可以添加一个终止的条件来引发错误
class AddOneIterator:
def __init__(self, start=0):
self.current = start # 初始化起始值
def __iter__(self):
return self
def __next__(self):
if self.current <= 10: # 添加一个if语句
x = self.current
self.current += 1
return x
else: # 当大于10的时候终止程序
raise StopIteration
# 创建一个加1的迭代器,从0开始
iterator = AddOneIterator()
for i in iterator:
print(i)
输出结果: 1 2 3 4 5 6 7 8 9 10
使用迭代器的好处
- 节省内存:迭代器允许按需要来生成数据,而不是一次性的将所有数据都加载到内存当中,这对于处理大型数据集非常有效
- 延迟计算:可以在需要的时候按照需要计算下一个元素,而不是提前计算所有的元素
生成器
生成器是一种特殊的迭代器,它用于创建迭代器
生成器允许你逐个产生值,而不是一次性创建并存储所有值
生成器通过在函数中使用 yield 语句来实现。yield是一个关键字,用于定义生成器函数每次调用生成器函数时,它都会返回一个生成器对象,这个对象可以记住函数执行的位置
当在生成器函数中使用 yield 语句时,函数的执行将会暂停,并将 yield 后面的表达式作为当前迭代的值返回。
然后,每次调用生成器的 next() 方法或使用 for 循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇到 yield 语句。这样,生成器函数可以逐步产生值,而不需要一次性计算并返回所有结果
实例
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
for value in gen:
print(value)
输出结果:1 2 3
实例
def count():
for i in range(1, 6): # range的结束索引是不包含的,所以使用6
yield i
# 使用生成器
c = count()
for number in c:
print(number)
输出结果:1 2 3 4 5
下面实例为使用yield实现斐波那契数列
#!/usr/bin/python3
import sys
def fibonacci(n): # 生成器函数 - 斐波那契
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
while True:
try:
print (next(f), end=" ")
except StopIteration:
sys.exit()
输出结果:0 1 1 2 3 5 8 13 21 34 55
使用生成器的好处
- 节省内存:因为生成器不需要一次性存储所有值
- 延迟计算:只有在需要时才计算下一个值
迭代器与生成器的区别
- 内存使用:生成器通常比迭代器更节省内存,因为它们是按需生成值的。
- 可迭代性:所有生成器都是迭代器,但不是所有迭代器都是生成器。例如,列表是一个迭代器,但不是生成器。
- 一次性:迭代器可以多次遍历,而生成器在遍历完成后就不能再次使用了,除非你重新创建它。
生成器提供了一种优雅的方式来处理数据流,特别是当数据集很大或者数据是按需生成的时候。而迭代器则提供了一种通用的方式来遍历任何可迭代对象。