Python中for 和 async for 的两种循环的核心区别,一文详解!(附代码示例)

forasync for 的核心区别在于:你在等“下一个数据”的时候,能不能干别的事。

简单来说:

  • 普通 for:是阻塞的。拿不到下一个数据,全程序卡死在那里等。

  • async for:是非阻塞的。在等下一个数据生成的间隙(比如等网络包、等数据库查询),程序可以去处理别的任务。

 

Async 的真正威力在于“同时做多件事”。

要看出区别,我们需要引入一个 “背景任务”(比如一个正在转圈的 Loading 动画,或者是背景心跳)。

  • 普通 For 循环:在等待数据时,整个世界都冻结了,背景动画会卡死。

  • Async For 循环:在等待数据时,背景动画还在跑

 

请运行下面这两段代码,差异非常巨大,可以方便更直观理解这两种循环的差异:

场景:一边下载大文件(模拟),一边播放 Loading 动画

1. ❌ 普通 For 循环(同步/阻塞)

你会发现:程序运行时,在这个 1 秒的等待期间,整个程序像“死机”了一样,没有任何反应,你也无法插入任何背景任务。

import time

print("=== 1. 普通同步模式开始 ===")

def sync_stream():
    for i in range(3):
        print(f"🔄 (生成器内部) 正在用力下载第 {i+1} 个包...")
        time.sleep(1) # 【死等】这里卡住了,CPU 不能去干别的事
        yield f"📦 包 {i+1} 下载完成"

start_time = time.time()

# 主循环
for data in sync_stream():
    # 在拿到 data 之前,这里是一片死寂,什么都做不了
    print(f"✅ 主程序收到: {data}\n")

print(f"=== 同步模式结束,总耗时: {time.time() - start_time:.2f}秒 ===")

实际执行效果:

image

 

 

2. ✅ Async For 循环(异步/非阻塞)

请仔细观察输出: 你会看到在 async for 等待数据的空档期,屏幕上还在不断打印 "💓 咚-咚-咚"

这证明了:async for 在等待时,让出了控制权,让背景任务(心跳)有机会运行!

import asyncio
import time

print("\n\n=== 2. 异步模式开始 (请注意观察心跳) ===")

# 这是一个背景任务,模拟 UI 动画或者心跳检测
async def background_heartbeat():
    while True:
        print("   💓 (背景任务) 咚-咚-咚... 程序还活着!")
        await asyncio.sleep(0.3) # 每0.3秒跳动一次

# 异步生成器
async def async_stream():
    for i in range(3):
        print(f"🔄 (生成器内部) 正在用力下载第 {i+1} 个包...")
        # 【挂起】告诉 Python:我要等1秒,这期间你去处理那个“心跳”任务吧
        await asyncio.sleep(1) 
        yield f"📦 包 {i+1} 下载完成"

async def main():
    # 1. 启动背景心跳任务
    task = asyncio.create_task(background_heartbeat())
    
    start_time = time.time()

    # 2. 开始 Async For 循环
    # 关键点:每次在这里“等”数据的时候,上面的 background_heartbeat 就会插队运行
    async for data in async_stream():
        print(f"✅ 主程序收到: {data}\n")

    # 停止心跳任务
    task.cancel()
    print(f"=== 异步模式结束,总耗时: {time.time() - start_time:.2f}秒 ===")

# 运行
asyncio.run(main())

实际执行效果:

image

 

直观差异图解

差异总结:

  1. 普通 for (Block)

    • 就像你去排队买奶茶。

    • 在店员做奶茶的 5 分钟里,你必须傻站在柜台前,不能玩手机,不能去厕所,完全被锁死。

  2. async for (Non-Block)

    • 就像你去拿号买奶茶。

    • 店员说“要等 5 分钟”,你拿到号(await)。

    • 在这 5 分钟里,你可以去隔壁买个面包,或者回个微信(运行背景任务)

    • 等奶茶好了(yield),你再回来取。

在上面的代码中,那个不断打印的 💓 咚-咚-咚 就是你在等待期间去买的面包。普通 for 循环是吃不到这个面包的。

 

posted @ 2025-12-11 15:51  AlphaGeek  阅读(114)  评论(0)    收藏  举报