一、迭代器(Iterator)
1.1 迭代器的定义
迭代器是一个可以被遍历的对象,通常用于从集合(如列表、元组、字典和集合)中逐个取出元素。Python 中的迭代器是遵循迭代器协议的对象,迭代器协议包含两个方法:__iter__()
和 __next__()
。
__iter__()
: 返回迭代器对象本身。__next__()
: 返回容器的下一个元素,如果没有元素了则抛出StopIteration
异常。
1.2 迭代器的实现
任何实现了上述两个方法的对象都可以称为迭代器。我们可以通过实现这两个方法来自定义一个迭代器。
class MyIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index < len(self.data):
result = self.data[self.index]
self.index += 1
return result
else:
raise StopIteration
# 使用自定义迭代器
my_iter = MyIterator([1, 2, 3, 4])
for item in my_iter:
print(item)
1.3 内置函数 iter() 和 next()
Python 提供了两个内置函数 iter()
和 next()
来支持迭代器。
iter(obj)
: 返回对象的迭代器。next(iterator, default)
: 从迭代器中获取下一个元素,如果迭代器到达末尾,则返回默认值(如果提供了默认值)。
numbers = [1, 2, 3, 4]
it = iter(numbers)
print(next(it)) # 输出: 1
print(next(it)) # 输出: 2
print(next(it)) # 输出: 3
print(next(it)) # 输出: 4
# print(next(it)) # 会抛出 StopIteration 异常
二、生成器(Generator)
2.1 生成器的定义
生成器是一种特殊的迭代器,用于生成一系列值。生成器允许你定义一个函数,每次调用该函数时可以生成一个值,而不是一次性返回所有值。生成器使用 yield
关键字代替 return
来生成值。
2.2 生成器的实现
生成器的实现非常简单,只需要定义一个包含 yield
关键字的函数。每次调用 yield
时,函数会暂停并返回一个值。下一次调用生成器的 __next__()
方法时,函数将从上次暂停的地方继续执行。
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
print(next(gen)) # 输出: 1
print(next(gen)) # 输出: 2
print(next(gen)) # 输出: 3
# print(next(gen)) # 会抛出 StopIteration 异常
2.3 生成器表达式
生成器表达式类似于列表推导式,但返回的是一个生成器对象,而不是一个列表。生成器表达式的语法非常简洁。
gen_exp = (x * x for x in range(5))
for val in gen_exp:
print(val)
2.4 生成器与迭代器的对比
- 内存使用:生成器在每次迭代时生成一个值,而不是一次性生成所有值,因此非常节省内存。相比之下,迭代器可能会占用更多的内存。
- 实现方式:迭代器需要实现
__iter__()
和__next__()
方法,而生成器通过定义包含yield
关键字的函数实现。 - 代码简洁性:生成器通常比自定义迭代器更简单、更易读。
三、迭代器与生成器的应用
3.1 延迟计算
生成器和迭代器常用于延迟计算,即在需要的时候才生成值,这在处理大量数据时尤为重要。例如,可以用生成器处理大文件,而不会将整个文件读入内存。
def read_large_file(file_path):
with open(file_path, 'r') as file:
for line in file:
yield line
for line in read_large_file('large_file.txt'):
process(line)
3.2 无限序列
生成器可以用于生成无限序列,例如斐波那契数列、素数等。
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
for _ in range(10):
print(next(fib))
3.3 管道处理
生成器还可以用于管道处理,将一个生成器的输出作为下一个生成器的输入,从而实现数据流的处理。
def generator1():
for i in range(5):
yield i
def generator2(gen):
for val in gen:
yield val * 2
pipeline = generator2(generator1())
for val in pipeline:
print(val)
Python 迭代器和生成器是强大且灵活的工具,适用于各种场景。迭代器允许我们自定义遍历行为,而生成器使我们能够轻松实现延迟计算、无限序列和管道处理。通过理解和使用这些工具,我们可以编写出高效且优雅的 Python 代码。