Python常用容器与导入语法详解(二)

一、queue.Queue:线程安全队列

queue.Queue主要用于多个线程之间安全地传递任务。

1. 导入Queue

复制代码
from queue import Queue

2. 创建队列

python 复制代码
task_queue = Queue()

限制最大容量:

python 复制代码
task_queue = Queue(maxsize=100)

maxsize=100表示队列最多保存100个尚未取出的元素。

3. 放入元素

python 复制代码
task_queue.put("任务1")
task_queue.put("任务2")

put()用于把元素加入队列。

4. 取出元素

复制代码
task = task_queue.get()

get()会取出最早加入的元素。

如果队列为空,默认情况下get()会阻塞等待新任务。

5. 标记任务完成

复制代码
task_queue.task_done()

这表示通过get()取出的一个任务已经处理完成。

等待所有任务处理完毕:

复制代码
task_queue.join()

join()会等待,直到所有加入队列的任务都已经调用对应的task_done()

6. 其他队列类型

python 复制代码
from queue import Queue, LifoQueue, PriorityQueue

三种类型分别为:

  • Queue:先进先出;
  • LifoQueue:后进先出;
  • PriorityQueue:优先级队列。

优先级队列示例:

python 复制代码
from queue import PriorityQueue

priority_queue = PriorityQueue()

priority_queue.put((2, "普通任务"))
priority_queue.put((1, "紧急任务"))

task = priority_queue.get()

print(task)

输出:

python 复制代码
(1, "紧急任务")

元组会先比较第一个元素,因此数字更小的任务会先取出。

二、asyncio.Queue:异步队列

asyncio.Queue用于多个协程之间传递数据。

1. 完整示例

python 复制代码
import asyncio

async def producer(queue: asyncio.Queue) -> None:
    await queue.put("工具执行结果")


async def consumer(queue: asyncio.Queue) -> None:
    result = await queue.get()
    print(result)
    queue.task_done()


async def main() -> None:
    queue = asyncio.Queue()

    await asyncio.gather(
        producer(queue),
        consumer(queue),
    )


asyncio.run(main())

2. async def是什么

python 复制代码
async def producer(queue: asyncio.Queue) -> None:

解释:

  • async def用于定义协程函数;
  • producer是函数名称;
  • queue是函数参数;
  • : asyncio.Queue是参数类型注解;
  • -> None是返回值类型注解;
  • 行末的:表示开始函数代码块。

类型注解主要用于:

  • 增强代码可读性;
  • 为IDE提供提示;
  • 配合静态类型检查工具;
  • 帮助框架读取参数信息。

普通类型注解默认不会自动完成运行时校验。

3. await是什么

python 复制代码
await queue.put("工具执行结果")

await表示等待一个可等待对象完成。

等待期间,当前协程可以暂时让出执行权,让事件循环执行其他协程。

从队列中获取元素:

python 复制代码
result = await queue.get()

如果队列为空,消费者协程会暂停等待,但不会像普通阻塞代码那样阻塞整个事件循环。

4. asyncio.gather是什么

python 复制代码
await asyncio.gather(
    producer(queue),
    consumer(queue),
)

gather()接收多个可等待对象,并发等待它们完成。这里生产者和消费者都会被提交给事件循环调度。

5. asyncio.run是什么

python 复制代码
asyncio.run(main())

它会:

  1. 创建事件循环;
  2. 运行main()协程;
  3. 等待main()完成;
  4. 清理异步任务;
  5. 关闭事件循环。

在普通Python脚本中,它通常是进入异步代码的入口。

三、array:固定类型数组

array用于保存类型相同的基础数据。

1. 导入array

复制代码
from array import array

2. 创建整数数组

复制代码
numbers = array("i", [10, 20, 30])

解释:

  • array是数组类型;
  • 第一个参数"i"是类型码;
  • "i"通常表示有符号整数;
  • 第二个参数是初始数据。

3. 添加元素

复制代码
numbers.append(40)

因为数组要求元素类型统一,下面代码会报错:

复制代码
numbers.append("hello")

普通业务开发中,大多数情况下使用list即可。当需要紧凑保存大量相同基础类型时,可以考虑array

四、三种队列应该如何选择

类型 主要使用场景
collections.deque 普通双端队列、滑动窗口、最近记录
queue.Queue 多线程之间传递任务
asyncio.Queue 多协程之间传递任务

普通同步代码:

python 复制代码
from collections import deque

queue = deque()
queue.append("任务")
task = queue.popleft()

多线程代码:

python 复制代码
from queue import Queue

queue = Queue()
queue.put("任务")
task = queue.get()

异步代码:

python 复制代码
import asyncio

queue = asyncio.Queue()

await queue.put("任务")
task = await queue.get()

最后一段代码中的await需要出现在协程函数等允许使用异步语法的环境中。


五、综合案例:统计工具调用结果

python 复制代码
from collections import Counter, defaultdict, deque
import heapq


records = [
    {
        "tool": "news_search",
        "status": "success",
        "latency_ms": 120,
    },
    {
        "tool": "market_analysis",
        "status": "success",
        "latency_ms": 180,
    },
    {
        "tool": "quotation_search",
        "status": "timeout",
        "latency_ms": 500,
    },
    {
        "tool": "news_search",
        "status": "success",
        "latency_ms": 100,
    },
    {
        "tool": "enterprise_search",
        "status": "error",
        "latency_ms": 80,
    },
]

1. 统计状态出现次数

复制代码
status_counter = Counter(
    record["status"]
    for record in records
)

下面这一部分:

复制代码
record["status"] for record in records

是生成器表达式。

它会:

  1. 遍历records
  2. 每次把当前记录保存到record
  3. 读取record["status"]
  4. 逐个把状态提供给Counter

2. 按工具名称分组

python 复制代码
records_by_tool = defaultdict(list)

for record in records:
    tool_name = record["tool"]
    records_by_tool[tool_name].append(record)

第一次访问某个工具名称时:

复制代码
records_by_tool[tool_name]

defaultdict会自动调用:

复制代码
list()

创建一个新的空列表。随后:

复制代码
.append(record)

把当前记录加入该工具对应的列表。

3. 保存最近三条记录

复制代码
recent_records = deque(
    records,
    maxlen=3,
)

这里:

  • records是初始数据;
  • maxlen=3表示最多保留三条;
  • 当数据超过三条时,只保留最后三条。

4. 找到最慢的两次调用

复制代码
slowest_records = heapq.nlargest(
    2,
    records,
    key=lambda record: record["latency_ms"],
)

它会根据每条记录的latency_ms字段进行比较,并返回耗时最大的两条记录。

5. 输出结果

复制代码
print("状态统计:", status_counter)
print("按工具分组:", dict(records_by_tool))
print("最近三条:", list(recent_records))
print("最慢两条:", slowest_records)

这里使用:

复制代码
dict(records_by_tool)

defaultdict转换成普通字典,方便打印或序列化。使用:

复制代码
list(recent_records)

deque转换成普通列表。


六、常见错误总结

1. 把append返回值赋给列表

错误:

复制代码
numbers = numbers.append(10)

正确:

复制代码
numbers.append(10)

append()直接修改原列表,返回值为None。

2. 使用空大括号创建集合

错误:

复制代码
values = {}

这会创建字典。

正确:

复制代码
values = set()

3. 使用list.pop(0)实现高频队列

不推荐:

复制代码
task = tasks.pop(0)

推荐:

复制代码
from collections import deque

tasks = deque()
task = tasks.popleft()

4. 给defaultdict传入list()

错误:

复制代码
groups = defaultdict(list())

正确:

复制代码
groups = defaultdict(list)

defaultdict需要一个可以稍后调用的默认工厂。

5. 认为heapify完成了整体排序

复制代码
heapq.heapify(numbers)

只保证堆性质,不保证列表完全有序。需要完整排序时使用:

复制代码
sorted_numbers = sorted(numbers)

6. 在普通函数中使用await

错误:

复制代码
def get_task(queue):
    task = await queue.get()

正确:

复制代码
async def get_task(queue):
    task = await queue.get()

await通常只能出现在通过async def定义的协程函数中。

十六、容器快速选择表

需求 推荐工具
保存有顺序、可修改的数据 list
保存有顺序、创建后不修改的数据 tuple
根据键查找值 dict
去重、集合运算 set
在两端高效添加和删除 deque
为缺失键自动创建默认值 defaultdict
统计元素出现次数 Counter
获取最小值、最大值或Top-K heapq
在线程之间传递任务 queue.Queue
在协程之间传递任务 asyncio.Queue
保存相同基础类型的数据 array

总结

Python最常用的四个内置容器是:

python 复制代码
list
tuple
dict
set

标准库中常用的扩展容器和工具包括:

python 复制代码
deque
defaultdict
Counter
heapq
queue.Queue
asyncio.Queue
array

学习一个容器时,不能只记住方法名称,还需要理解:

  • 容器是否保留顺序;
  • 容器是否可以修改;
  • 是否允许重复元素;
  • 元素是否需要可哈希;
  • 查询、插入和删除的大致时间复杂度;
  • 容器是否支持线程或协程场景;
  • 方法是直接修改原对象,还是返回新对象;
  • 方法的返回值是什么。

掌握这些容器后,下一篇我们就可以继续学习Python函数、类、装饰器、迭代器、生成器、asyncio和FastAPI后端开发。

相关推荐
维基框架1 小时前
坊间传闻 OpenAI 将要发布GPT-6 Sol 模型
人工智能·pytorch·python
Cccp.1231 小时前
【leetcode】(六) 图和贪心算法
数据结构·算法·leetcode
读研的武1 小时前
Python异步编程
python
y1su1 小时前
【Leetcode】1477. 找两个和为目标值且不重叠的子数组
数据结构·后端·算法·leetcode·职场和发展
宸津-代码粉碎机1 小时前
Java面试核心:JVM三大GC垃圾回收算法原理与生产场景落地分析
java·大数据·人工智能·python·spring
小静AI工程实验室1 小时前
Codex 实用教程:Windows、macOS、Linux 安装配置到首个可验收项目
人工智能·python·开发工具·codex
空空潍1 小时前
2026年软考中级软件设计师(二):数据结构
数据结构·软考·软件设计师·软设
黑马水牛2 小时前
Carla仿真系列:17_利用Carla仿真环境跑通3DGS——从采集360张图到高斯泼溅建模
python·ros·colmap·3dgs·新视角合成·carla仿真·三维建图
赵大仁3 小时前
极空间 NAS 没有命令行,我逆向了它的桌面客户端
python·ai编程·nas·mcp·极空间