Python - 迭代器

你好,有抱负的Python程序员们!今天,我们将开始一段激动人心的旅程,进入Python迭代器的世界。作为你友好的邻居计算机科学老师,我很激动能引导你通过这个迷人的话题。所以,拿起你最喜欢的饮料,舒服地坐好,让我们开始吧!

Python - Iterators

Python 迭代器

迭代器是什么?

想象你有一个装满彩色乐高积木的大盒子。迭代器就像一只神奇的手,可以伸进盒子里一次取出一个乐高积木,让你逐个检查每个积木,而不需要把盒子里的所有东西都倒在地上。在Python中,迭代器的工作方式类似,让我们可以一次处理一个数据集合中的项目。

迭代器如何工作?

Python中的迭代器是实现了两个特殊方法的对象:__iter__()__next__()。如果这听起来现在像天书也不要担心——我们会一步一步地解释!

  1. __iter__() 方法返回迭代器对象本身。这就像在说,“嘿,我准备好开始分发乐高积木了!”
  2. __next__() 方法返回序列中的下一个项目。这就像伸进盒子,取出下一个乐高积木。

让我们用一个简单的例子来看看这是如何工作的:

# 创建一个列表(我们的乐高积木盒子)
my_list = [1, 2, 3, 4, 5]

# 从列表中获取一个迭代器
my_iterator = iter(my_list)

# 使用 next() 逐个获取项目
print(next(my_iterator))  # 输出:1
print(next(my_iterator))  # 输出:2
print(next(my_iterator))  # 输出:3

在这个例子中,iter(my_list) 为我们的列表创建了一个迭代器对象。然后,每次调用 next(my_iterator) 都会从列表中检索下一个项目。

迭代器在循环中的力量

这里有一个有趣的事实:当你在Python中使用 for 循环时,你实际上是在幕后使用迭代器!让我们看看是如何实现的:

my_list = ["苹果", "香蕉", "樱桃"]

for fruit in my_list:
print(f"我喜欢 {fruit}!")

# 输出:
# 我喜欢 苹果!
# 我喜欢 香蕉!
# 我喜欢 樱桃!

Python自动从 my_list 创建一个迭代器,并使用 __next__() 获取循环的每个项目。这不是很巧妙吗?

迭代器中的错误处理

现在,当我们的神奇乐高积木检索手伸进一个空盒子时会发生什么?在Python术语中,当迭代器中没有更多的项目时会发生什么?这时就需要进行错误处理。

当一个迭代器耗尽(没有更多项目)时,它会引发一个 StopIteration 异常。让我们看看这是如何发生的:

my_list = [1, 2, 3]
my_iterator = iter(my_list)

print(next(my_iterator))  # 输出:1
print(next(my_iterator))  # 输出:2
print(next(my_iterator))  # 输出:3
print(next(my_iterator))  # 引发 StopIteration 异常

为了优雅地处理这个问题,我们可以使用 try-except 块:

my_list = [1, 2, 3]
my_iterator = iter(my_list)

try:
while True:
item = next(my_iterator)
print(item)
except StopIteration:
print("到达迭代器末尾!")

# 输出:
# 1
# 2
# 3
# 到达迭代器末尾!

这样,我们可以处理所有项目并平滑地处理迭代器的结束。

自定义迭代器

现在我们知道了迭代器是如何工作的,让我们创建自己的迭代器!想象我们想要创建一个倒计时迭代器。以下是我们如何做到这一点:

class Countdown:
def __init__(self, start):
self.start = start

def __iter__(self):
return self

def __next__(self):
if self.start <= 0:
raise StopIteration
self.start -= 1
return self.start + 1

# 使用我们的自定义迭代器
countdown = Countdown(5)
for number in countdown:
print(number)

# 输出:
# 5
# 4
# 3
# 2
# 1

在这个例子中,我们创建了一个 Countdown 类,它既是一个可迭代的(它有一个 __iter__() 方法),也是一个迭代器(它有一个 __next__() 方法)。每次调用 __next__() 时,它都会返回倒计时序列中的下一个数字。

异步迭代器

当我们进入更高级的领域时,让我们简要地谈谈异步迭代器。这些用于异步编程,这是一种编写并发代码的方式。

异步迭代器与常规迭代器类似,但它使用 asyncawait 关键字。以下是一个简单的例子:

import asyncio

class AsyncCountdown:
def __init__(self, start):
self.start = start

def __aiter__(self):
return self

async def __anext__(self):
await asyncio.sleep(1)  # 模拟一些异步操作
if self.start <= 0:
raise StopAsyncIteration
self.start -= 1
return self.start + 1

async def main():
async for number in AsyncCountdown(5):
print(number)

asyncio.run(main())

# 输出(每隔1秒):
# 5
# 4
# 3
# 2
# 1

这个异步迭代器的工作方式与我们的 Countdown 类似,但它允许进行异步操作(在这里用 asyncio.sleep(1) 模拟)。

迭代器方法表

以下是我们讨论的关键方法的便捷表格:

方法 描述 用于
__iter__() 返回迭代器对象 常规迭代器
__next__() 返回序列中的下一个项目 常规迭代器
__aiter__() 返回异步迭代器对象 异步迭代器
__anext__() 返回异步序列中的下一个项目 异步迭代器

就这样,各位!我们已经穿越了Python迭代器的领域,从基础到创建我们自己的,甚至触及了异步迭代器。记住,就像学习用乐高积木搭建一样,掌握迭代器需要练习。所以,不要害怕实验并构建你自己的迭代器。快乐编程,愿迭代器与你同在!

Credits: Image by storyset