Python 数据类型与数据结构

Python 内置类型总图:标量、序列、映射、集合与二进制类型;用可变/不可变与典型场景建立阶段二阅读入口。

#type / concept #status / growing #resource / python #tech / lang / python #tech / dev

[!info] 关联笔记

Python 数据类型与数据结构

这个概念为什么出现

Python 日常编码 80% 的时间在和内置容器与标量打交道。没有一张总图时,人容易:

  • 该用 tuple 却用了 list
  • 该用 set 去重却手写双重循环
  • bytesstr 处理网络报文

本篇是地图,不是把每个容器写到实现级;细规则由阶段二原子笔记承担。

[!abstract] 一句话理解 Python 内置类型按标量、序列、映射、集合与二进制分组;先判断“是否可变、是否有序、键/元素约束”,再选结构。

最小可运行示例

先把示例放进业务场景,再看代码:

场景:活动报名后台做一次轻量汇总

运营后台读到一批报名记录,需要:

  • list 保序展示
  • set 统计去重用户
  • dict 聚合渠道计数
  • tuple 做不可变的配置键
# signup_structures_map.py
# 业务意图:用四种核心容器完成报名汇总。
# 教学点:
# - list 有序可改;tuple 有序不可变;
# - set 去重;dict 做聚合;
# - 容器里装的是对象引用。

from collections import Counter


def summarize_signups(rows: list[dict]) -> dict:
    # rows: [{"user": "u1", "channel": "wechat"}, ...]
    ordered_users = []  # 保序展示(可含重复报名意图时另议)
    unique_users: set[str] = set()
    for row in rows:
        ordered_users.append(row["user"])
        unique_users.add(row["user"])

    channel_counts = Counter(row["channel"] for row in rows)
    # 不可变配置键示例:环境 + 活动代码
    cache_key = ("prod", "spring-sale")

    return {
        "ordered_users": ordered_users,
        "unique_count": len(unique_users),
        "channels": dict(channel_counts),
        "cache_key": cache_key,
    }


def main() -> None:
    rows = [
        {"user": "alice", "channel": "wechat"},
        {"user": "bob", "channel": "app"},
        {"user": "alice", "channel": "wechat"},
    ]
    print(summarize_signups(rows))


if __name__ == "__main__":
    main()

建议运行:

python signup_structures_map.py

期望输出:

{'ordered_users': ['alice', 'bob', 'alice'], 'unique_count': 2, 'channels': {'wechat': 2, 'app': 1}, 'cache_key': ('prod', 'spring-sale')}

结合场景再看三个关注点

  1. 同一用户出现两次:list 保留事件流,set 回答“多少独立用户”。
  2. dict/Counter 适合聚合;不要滥用 list 线性扫描当主索引。
  3. tuple 作键要求元素可哈希;list 不能当 dict 键。

核心概念与准确模型

内置类型地图

类别类型有序可变典型场景
数值int, float, complex计数、度量
文本str文案、标识
布尔/空bool, None标志、缺失
序列list, tuple, rangelist 是 / 其余否列表、记录、范围
映射dict插入序索引、JSON 对象
集合set, frozensetset 是去重、成员测试
二进制bytes, bytearray, memoryview仅 bytearray 等网络、文件

可变与不可变(总原则)

  • 不可变:对象值不可改;“修改”通常产生新对象再绑定。
  • 可变:可原地改;多名字共享时彼此可见。
  • 容器不可变 ≠ 其元素若可变就“深不可变”(tuple 可装 list)。

选择启发式

  1. 要索引与保序可变序列 → list
  2. 固定字段小记录 / 可哈希序列 → tuple
  3. 键值检索与聚合 → dict
  4. 去重与集合运算 → set
  5. 文本 → str;字节协议 → bytes

边界情况与反直觉行为

  1. 空容器真值:空 list/dict/set/"" 为假。
  2. dict 键必须可哈希;自定义对象需正确 __hash__/__eq__
  3. 大 list 头删 pop(0) 昂贵;队列场景看 deque

常见误区

[!warning] 常见误区:只有 list 一种序列 错误理解:所有一串数据都用 list。
正确模型:固定结构、作键、防误改时优先 tuple;成员测试频繁用 set。

工程实践

  • API 边界:输入 list/dict 是否会被函数原地修改要写清。
  • JSON 对应:object→dict,array→list,string→str,null→None。
  • 性能:先选对结构,再谈微观优化。

本节总结

本篇给你选型地图。下一步应按路线进入 list/tuple、dict、可变性与字符串专篇,而不是在一页堆完所有方法表。

自测题

  1. 为什么 cache_key 用 tuple 而不是 list?
  2. 统计独立用户为什么需要 set(或等价结构)?
参考答案
  1. 需要不可变且可哈希,才能稳定当键/缓存标识;list 不可哈希。
  2. set 平均 O(1) 成员测试/去重,表达“集合”语义比双层 list 扫描清晰。

延伸阅读与资料来源

资料类型支撑内容
Built-in Types文档类型行为
Tutorial – Data Structures教程容器入门
创建于 2026/3/24 更新于 2026/7/15