0

0

如何实现一个支持 aiter 的异步可迭代类

冷炫風刃

冷炫風刃

发布时间:2026-01-26 18:53:02

|

798人浏览过

|

来源于php中文网

原创

直接实现__aiter__不够,因为Python要求异步迭代器必须同时实现__aiter__(普通方法,返回自身或新对象)和__anext__(async方法,返回值或抛出StopAsyncIteration),仅__aiter__返回异步生成器或缺失__anext__会导致TypeError。

如何实现一个支持 aiter 的异步可迭代类

为什么直接实现 __aiter__ 不够

很多开发者以为只要在类里加个 __aiter__ 方法返回一个异步生成器或自定义对象就完事了,但 Python 会检查该方法是否返回了真正符合 AsyncIterator 协议的对象——即必须同时实现 __aiter____anext__。如果只实现 __aiter__ 并直接 return self,而没提供 __anext__,运行时会报 TypeError: 'X' object is not an async iterator

常见错误写法:

class BadAsyncIter:
    def __init__(self, items):
        self.items = items
    async def __aiter__(self):
        for item in self.items:
            yield item  # ❌ 这是 async generator,但 __aiter__ 不能直接 yield

上面代码看似合理,实则语法错误:async def __aiter__ 中不允许 yield(除非用 yield + await 配合 async for 内部机制,但那不是标准用法)。

正确实现:分离 __aiter____anext__

标准做法是让 __aiter__ 返回一个独立对象(通常是自身),该对象实现了 __anext__ 并维护迭代状态。关键点:

  • __aiter__ 必须是普通方法(非 async),返回 self 或另一个支持 __anext__ 的对象
  • __anext__ 必须是 async 方法,返回下一个值;迭代结束时抛出 StopAsyncIteration
  • 状态(如当前索引)必须保存在实例属性中,因为每次 __anext__ 调用都可能跨 await 边界

示例(内存列表模拟异步数据源):

class AsyncList:
    def __init__(self, items):
        self.items = items
        self._index = 0
def __aiter__(self):
    return self  # ✅ 返回自身,要求自身有 __anext__

async def __anext__(self):
    if self._index >= len(self.items):
        raise StopAsyncIteration
    item = self.items[self._index]
    self._index += 1
    return item

使用方式:

百度文心百中
百度文心百中

百度大模型语义搜索体验中心

下载
async for x in AsyncList([1, 2, 3]):
    print(x)

如何支持带延迟或 I/O 的真实异步场景

上面例子只是同步逻辑包装成异步接口。若要模拟真实异步行为(如从网络/数据库分页拉取),__anext__ 内应包含 await 调用:

  • 每次 __annext__ 可以 await asyncio.sleep(0.1) 模拟延迟
  • 也可以 await aiohttp.ClientSession.get(...) 获取下一页数据
  • 注意:不能在 __aiter__ 中做耗时 await,它必须快速返回迭代器对象
  • 若需预加载或缓存,建议在 __aiter__ 中初始化缓冲区(如 self._buffer = []),再由 __anext__ 动态填充

示例(带延迟的计数器):

import asyncio

class DelayedCounter: def init(self, start=0, stop=3): self.start = start self.stop = stop self._current = start

def __aiter__(self):
    return self

async def __anext__(self):
    if self._current >= self.stop:
        raise StopAsyncIteration
    await asyncio.sleep(0.01)  # ✅ 真实异步等待
    value = self._current
    self._current += 1
    return value

兼容性与调试陷阱

Python 3.7+ 支持 async for,但部分旧版类型检查器(如 mypy ≤ 0.930)可能不识别自定义 __aiter__,需加类型提示:

  • 显式继承 typing.AsyncIterator[T](仅用于类型提示,不参与运行)
  • mypy 要求 __anext__ 注解返回 Coroutine[None, None, T]
  • 若用 asyncio.Queueaiostream.stream 等第三方库替代手写,要注意它们内部已封装好协议,但失去对迭代逻辑的细粒度控制
  • 测试时别忘了:async for 无法在普通函数中直接运行,必须包在 async def 里并用 asyncio.run()

最容易被忽略的是状态重用问题:同一个 AsyncList 实例被多次 async for 时,_index 不会自动重置。如需可重入,应在 __aiter__ 中返回新对象,而不是 return self

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

778

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

686

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

769

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

740

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1445

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

571

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

581

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

752

2023.08.11

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

31

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.3万人学习

Django 教程
Django 教程

共28课时 | 3.5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号