Python asyncio中能否将__contains__适配为协程并配合in使用?
问题:如何将Python的__contains__适配为asyncio协程方法?
能否将Python的__contains__函数适配到asyncio中,使其成为协程方法?示例代码如下:
class A(): async def __contains__(self, a): return True async def main(): a = A() print(2 in a)
运行上述代码会产生警告:
RuntimeWarning: coroutine 'A.contains' was never awaited
我认为需要适配asyncio的特殊版本in运算符,但尝试了多种await与in的组合均未成功。实际场景为通过数据库搜索检查实体冲突,如判断用户名'mike'是否存在于Users表中,即'mike' in Users。虽可自定义contains方法如User.contains('mike'),但更倾向于in的简洁写法。
解决方案
Python的in运算符本身不支持异步的__contains__方法——当你使用item in container时,解释器会直接调用container.__contains__(item),但不会自动await返回的协程对象,这就是你看到警告的原因,而且此时得到的结果是协程对象而非布尔值。
目前Python语法没有提供直接支持异步in判断的语法糖,但可以通过以下两种方式实现类似的简洁效果:
方案1:自定义异步contains方法
这是最直接的实现方式,逻辑清晰且符合异步规范:
import asyncio class Users: async def contains(self, username): # 模拟异步数据库查询逻辑 await asyncio.sleep(0.1) return username == 'mike' async def main(): users = Users() exists = await users.contains('mike') print(exists) # 输出: True asyncio.run(main())
方案2:封装成贴近in语法的辅助函数
如果想更贴近in的写法,可以封装一个通用的辅助函数,兼容异步和同步两种__contains__实现:
import asyncio async def a_in(item, container): # 检查容器是否有异步的__contains__方法 if hasattr(container, '__contains__') and asyncio.iscoroutinefunction(container.__contains__): return await container.__contains__(item) # 兼容普通同步的__contains__ return item in container class Users: async def __contains__(self, username): await asyncio.sleep(0.1) return username == 'mike' async def main(): users = Users() exists = await a_in('mike', users) print(exists) # 输出: True asyncio.run(main())
为什么不能直接用await配合in?
Python的运算符优先级和语法规则限制了这种写法:
await item in container会被解析为(await item) in container,即先await item,再判断结果是否在container中,这和我们的需求不符。item in await container要求container是一个可await对象,且其返回值支持in判断,但这需要你将整个Users对象设计为可await的,显然不符合检查实体存在的场景。
总结来说,虽然无法直接让in运算符支持异步__contains__,但通过上述两种方案,可以在满足异步数据库查询需求的同时,保持代码的简洁性。
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

