Python从入门到实战(六):非序列容器

📅 2026/7/8 6:21:33
Python从入门到实战(六):非序列容器
目录一、集合1. 集合概述与特点2. 集合定义与嵌套3. 集合的增删改查3.1 增3.2 删3.3 改3.4 查4. 数学运算5. 循环遍历二、字典1. 字典概述与特点2. 字典的定义与嵌套3. 字典的增删改查3.1 增/改3.2 删3.3 查4. 循环遍历三、数据容器通用操作1. 统计与度量函数2. 排序与逆序函数3. 结构转换与组合4. 逻辑判断函数四、数据容器对比1. 五种容器特性概述2. 数据容器对比五、综合案例1. 案例一文本单词频次统计2. 案例二数据去重与集合运算总结一、集合1. 集合概述与特点在 Python 中集合Set是一种无序且无重复元素的集合数据结构。与列表和元组等序列类型不同集合不记录元素的插入顺序也不支持通过索引访问特定的元素集合的核心特点包括确定性集合中的元素必须是明确的唯一性集合内不允许存在重复的元素。若向集合中添加已存在的元素集合不会发生变化。该特性使集合成为数据去重的高效工具无序性集合中的元素没有固定的顺序遍历集合时输出的元素顺序可能与构建时不同元素不可变性集合是可变容器但其中的元素必须是不可变类型即可哈希对象如整数、浮点数、字符串或元组等。因此列表、字典或其他集合本身不能作为普通集合的元素2. 集合定义与嵌套在 Python 中可以通过两种主要方式定义集合使用大括号 {} 或内置函数 set()使用大括号定义 直接将多个元素用逗号隔开并包裹在大括号内# 定义一个包含整数的集合 numbers {1, 2, 3, 4, 5}使用 set 函数定义 可以通过 set() 将其他可迭代对象如列表、元组、字符串转换为集合# 从列表创建集合 char_set set([a, b, c]) # 结果为 {a, b, c}空集合的定义 定义空集合必须使用 set()而不能使用 {}因为 {} 在Python中默认用于定义空字典empty_set set() # 正确的空集合定义集合的嵌套由于集合的元素必须是可哈希不可变的因此普通的 set 不能嵌套自身即集合的元素不能是另一个 set如果需要实现集合的嵌套必须使用 Python 提供的不可变集合类型——frozenset冰冻集合。frozenset 一经创建便无法修改因此它是可哈希的可以作为普通集合的元素# 正确的集合嵌套示例 nested_set {frozenset({1, 2}), frozenset({3, 4})}3. 集合的增删改查集合不支持索引因此其 改 与 查 的操作逻辑与序列类型有所不同。以下是集合的操作方法3.1 增add(element)向集合中添加单个元素。如果元素已存在则不进行任何操作s {1, 2} s.add(3) # s 变为 {1, 2, 3}update(iterable)用于一次性添加多个元素参数必须是可迭代对象如列表、元组或其他集合s {1, 2} s.update([3, 4], {5, 6}) # s 变为 {1, 2, 3, 4, 5, 6}3.2 删remove(element)移除指定元素。若元素不存在会触发 KeyError 异常s {1, 2, 3} s.remove(2) # s 变为 {1, 3}discard(element)移除指定元素。若元素不存在程序不会报错操作静默完成s {1, 2, 3} s.discard(4) # 不报错s 仍为 {1, 2, 3}pop()随机移除并返回集合中的一个元素。由于集合无序无法预测被移除的元素。若集合为空会触发 KeyErrorclear()清空集合中的所有元素使其成为空集合3.3 改注意集合没有下标也不支持 replace 方法所以集合没有专门用于 改 的方法但可以使用remove add 的组合来达到 修改 的效果# 将 20 改为 66 s1 {10, 20, 30, 40, 50} s1.remove(20) s1.add(66)3.4 查集合无法通过索引查询特定位置的元素但可以通过 in 和 not in 关键字检测某个元素是否存在于集合中。由于集合基于哈希表实现其查找的时间复杂度为 O(1)效率远高于列表s {1, 2, 3} print(2 in s) # 输出: True print(4 not in s) # 输出: True4. 数学运算Python 集合完整支持数学意义上的集合论运算包括交集、并集、差集和对称差集。这些运算可以通过运算符或对应的方法实现运算类型运算符对应方法说明并集a | ba.union(b)返回包含两集合所有元素的新集合交集a ba.intersection(b)返回同时存在于两集合中的元素的新集合差集a - ba.difference(b)返回存在于 a 但不存在于 b 中的元素的新集合对称差集a ^ ba.symmetric_difference(b)返回两集合非共有元素组成的新集合此外还可以通过以下方法判断集合间的关系issubset()判断当前集合是否为另一个集合的子集issuperset()判断当前集合是否为另一个集合的超集isdisjoint()判断两个集合是否没有交集5. 循环遍历虽然集合是无序的但它属于可迭代对象可以使用 for 循环遍历其中的每一个元素。需要注意的是遍历输出的顺序不代表任何特定的规律fruits {apple, banana, cherry} for fruit in fruits: print(fruit)二、字典1. 字典概述与特点在Python中字典Dictionary是一种映射类型的非序列容器。它以键值对的形式存储数据其中 键 与 值 之间存在一一对应的映射关系。字典常用于存储结构化数据以及需要通过特定标识符快速查找对应数据的场景字典的核心特点包括键的唯一性与不可变性字典中 键Key必须是唯一的不允许存在重复的键。同时键必须是不可变类型可哈希对象如整数、浮点数、字符串或元组。列表、字典或集合等可变对象不能作为字典的键值的任意性字典中的 值Value可以是任意数据类型包括动态对象、列表、甚至另一个字典。值不需要唯一多个不同的键可以映射到相同的值有序性在早期版本的 Python 中字典是无序的。但自 Python 3.7 起字典正式确保持有元素的插入顺序。遍历字典时将按照键值对被添加的先后顺序输出高效查找字典内部基于哈希表实现。与通过遍历匹配元素的列表不同字典通过键直接定位值其查找、插入和删除操作的平均时间复杂度均为 O(1)2. 字典的定义与嵌套定义字典主要有使用大括号和使用内置函数 dict() 两种方式使用大括号定义 每个键值对使用冒号分隔多个键值对之间用逗号,隔开整体包裹在大括号内# 定义一个存储用户信息的字典 user_info {name: Alice, age: 25, is_admin: False}使用 dict 函数定义 可以通过传递关键字参数或传入包含双元组的可迭代对象来创建字典# 方式一关键字参数 d1 dict(nameBob, age30) # 方式二双元组列表 d2 dict([(name, Bob), (age, 30)]) print(d1) print(d2)空字典的定义 直接使用空的大括号或不带参数的 dict() 函数empty_dict_1 {} empty_dict_2 dict()字典嵌套由于字典的值可以接收任意数据类型因此字典可以实现多层嵌套。字典嵌套常用于表示复杂的层级结构例如 JSON 数据# 字典嵌套示例存储多名学生的信息 students { 1001: {name: 张三, scores: {math: 95, english: 88}}, 1002: {name: 李四, scores: {math: 92, english: 90}} }3. 字典的增删改查对字典的操作主要是围绕键值对进行的。由于字典通过键进行索引其操作逻辑高度依赖于键的存在性。3.1 增/改在字典中增加和修改元素使用相同的语法。通过 dict[key] value 进行赋值时若对应的键不存在则会在字典中追加该键值对增若对应的键已存在则会覆盖原有的值改info {name: Alex} # 键不存在执行添加操作 info[age] 18 # info 变为 {name: Alex, age: 18} print(info) # 键已存在执行修改操作 info[name] Alexander # info 变为 {name: Alexander, age: 18} print(info)update([other])使用另一个字典或可迭代的键值对来更新当前字典。若键存在则覆盖不存在则添加info.update({age: 20, gender: male})3.2 删del dict[key]删除指定的键值对。若键不存在会触发 KeyError 异常pop(key[, default])移除指定键并返回对应的值。若键不存在且未提供 default 参数会触发 KeyError若提供了 default则返回该默认值age info.pop(age, None) # 安全删除若不存在则返回 Nonepopitem()移除并返回字典中的最后一个键值对。返回的结果是一个 (key, value) 形式的元组clear()清空字典中的所有键值对3.3 查下标访问 dict[key]直接通过键获取值。如果键不存在会直接抛出 KeyErrorget(key[, default])安全的访问方法。若键存在返回对应的值若键不存在则返回 default 参数指定的值默认为 None而不会引发程序中断# 推荐的访问方式 gender info.get(gender, unknown) print(gender)4. 循环遍历字典提供了三种视图对象View Objects分别用于遍历键、值或键值对。这些对象会随着字典的改变进行动态更新遍历键Keys 直接遍历字典对象或调用 keys() 方法# 默认遍历的就是键 for key in info: print(key)遍历值Values 调用 values() 方法for value in info.values(): print(value)遍历键值对Items 调用 items() 方法通常配合元组拆包使用for key, value in info.items(): print(fKey: {key}, Value: {value})三、数据容器通用操作在 Python 中有许多内置的全局函数并不局限于特定的容器类型而是适用于几乎所有的数据容器包括列表、元组、字符串、集合与字典。将这些通用操作归纳在此处有助于理解 Python 的数据结构体系1. 统计与度量函数len(iterable)返回容器中元素的个数对于字典返回的是键值对的数量。所有标准容器在底层都实现了 __len__ 方法因此该操作的时间复杂度为 O(1)len([1, 2, 3]) # 列表: 3 len({a: 1, b: 2}) # 字典: 2max(iterable) / min(iterable)分别返回容器中的最大值和最小值如果容器是字典默认对键Keys进行比较可以通过 key 参数传入一个函数以此自定义比较的规则若容器为空且未提供 default 参数会触发 ValueErrormax({1, 5, 3}) # 集合: 5 max({a: 10, b: 5}) # 字典按键比较: b max({a: 10, b: 5}.values()) # 字典按值比较: 10sum(iterable)计算容器中所有元素的累加和。容器中的元素必须是数值类型如整数、浮点数否则会触发 TypeErrorsum({1, 2, 3}) # 集合: 62. 排序与逆序函数sorted(iterable)对容器中的元素进行排序。无论输入的容器是什么类型sorted() 都会返回一个全新的列表原容器的内部结构和顺序不会发生改变key 参数用于指定一个函数在每个元素比较前先进行调用reverseTrue 表示降序排列s {3, 1, 4, 2} sorted_list sorted(s) # 返回列表: [1, 2, 3, 4]原集合 s 不变 d {c: 1, a: 3, b: 2} sorted(d) # 对字典的键排序返回: [a, b, c]reversed(seq)返回一个反向迭代器。注意该函数仅适用于序列类型如列表、元组、字符串和确定具有顺序的容器。由于普通集合是无序的因此对集合执行 reversed() 会触发 TypeError3. 结构转换与组合enumerate(iterable)将一个可迭代对象组合为一个索引序列每次迭代时返回一个包含 (index, element) 的元组。常用于在 for 循环中同时获取索引和元素值for index, value in enumerate([a, b, c]): print(index, value) # 输出: 0 a, 1 b, 2 czip(*iterables)将多个可迭代对象打包成元组然后返回一个由这些元组组成的迭代器keys [name, age] values [Alice, 25] # 结合 dict() 可以直接将两个序列转换为字典 result dict(zip(keys, values)) # {name: Alice, age: 25}4. 逻辑判断函数any(iterable)判断容器中是否至少有一个元素的布尔值为 True。如果容器中有一个元素为真则返回 True如果容器为空或所有元素都为假则返回 Falseany([0, False, 1]) # 返回 True any([]) # 空容器返回 Falseall(iterable)判断容器中是否所有元素的布尔值都为 True。只有当容器内所有元素均为真时才返回 True如果容器为空all() 的返回值是 True在逻辑学中被称为 空真理Vacuous Truthall([1, True, hello]) # 返回 True all([1, 0, True]) # 返回 False因为包含0 all([]) # 空容器返回 True四、数据容器对比为了在实际开发中能够准确、高效地选择合适的数据容器我们需要对 Python 的五种核心数据容器List、Tuple、String、Set、Dict在技术特性上进行对比1. 五种容器特性概述列表List一种可变的、有序的无约束序列。支持任意类型对象的存储支持重复元素通过索引进行 O(1) 的定位但在执行包含性查找如 in 操作或在非末尾位置插入/删除元素时时间复杂度为 O(n)元组Tuple一种不可变的、有序的无约束序列。其特性与列表高度相似但由于其不可变性元组通常用于表示结构化的常量数据。此外元组可以用作字典的键或集合的元素前提是元组内部不包含可变对象字符串String一种不可变的、有序的单一类型序列。字符串专门用于存储文本字符。由于字符在内存中是连续存储的且具有不可变性对其进行修改操作实质上都会创建全新的字符串对象集合Set一种可变的、无序的唯一性非序列容器。集合通过哈希表实现元素必须是不可变可哈希类型。集合天然具备去重功能并且其元素的查找、添加、删除操作在平均情况下的时间复杂度均为 O(1)字典Dict一种可变的、有序的Python 3.7 保持插入顺序键值对映射容器。字典的键必须唯一且不可变而值可以为任意类型。它同样基于哈希表实现能够通过键以 O(1) 的时间复杂度快速检索对应的值2. 数据容器对比类型是否有序是否可变唯一性类型约束底层实现常见应用场景查找复杂度List是是允许重复无约束可存储任意类型动态数组存储、遍历和动态修改一组同类数据O(n)Tuple是否允许重复无约束可存储任意类型静态数组配置文件、函数多返回值、作为字典的键O(n)String是否允许重复仅能存储字符连续字符内存块文本处理、数据传输与展示O(n)Set否是必须唯一必须是不可变类型哈希表数据去重、数学集合运算O(1)Dict是是键唯一(值可重复)键必须不可变值无约束哈希表存储结构化数据、需要通过Key快速检索的场景O(1)五、综合案例为了更好地理解非序列容器集合与字典在实际开发中的应用本节将通过两个典型案例展示如何利用它们的特性解决具体问题1. 案例一文本单词频次统计场景描述给定一段英文文本需要统计该文本中每个单词出现的次数并输出频次最高的前三个单词技术分析此案例需要建立 单词 - 频次 的映射关系最适合使用字典。同时由于要对频次进行降序排列需结合第三部分介绍的 sorted() 通用函数# 原始文本数据 text python is powerful python is open source python data science is growing # 1. 将文本按空格切分为单词列表 words text.split() # 2. 统计词频 word_counts {} for word in words: # 使用 get() 方法处理键不存在的情况若不存在则初始记为 0然后加 1 word_counts[word] word_counts.get(word, 0) 1 print(完整统计结果, word_counts) # 3. 按词频Dict 的 Value进行降序排序并取前三名 # 利用 sorted 的 key 参数指定按字典的值进行比较 top_three sorted(word_counts.items(), keylambda item: item[1], reverseTrue)[:3] print(\n词频最高的前三个单词) for word, count in top_three: print(f单词: {word}, 出现次数: {count})2. 案例二数据去重与集合运算场景描述现有两个线上活动的用户抽奖参与记录允许单人多次提交生成了包含重复用户ID的列表。需求为分别获取两个活动的不重复参与用户总数找出同时参与了这两个活动的活跃用户。技术分析利用集合的唯一性可以完成数据去重利用集合的交集运算可以高效筛选出同时满足两个条件的数据# 活动 A 和活动 B 的原始参与记录包含大量重复 ID activity_a_records [user_101, user_102, user_101, user_103, user_102] activity_b_records [user_103, user_104, user_105, user_103, user_101] # 1. 利用集合自动去重 unique_users_a set(activity_a_records) unique_users_b set(activity_b_records) print(f活动 A 独立参与人数: {len(unique_users_a)} 人 (去重后: {unique_users_a})) print(f活动 B 独立参与人数: {len(unique_users_b)} 人 (去重后: {unique_users_b})) # 2. 运用数学运算求交集找出同时参与两项活动的用户 core_users unique_users_a unique_users_b print(f同时参与两项活动的核心用户: {core_users}) # 输出: {user_101, user_103}总结本章继续学习了 Python 中另外两种重要的数据容器——集合和字典并对 Python 五种核心数据容器进行了系统梳理。通过本章的学习我们不仅掌握了集合和字典的创建、增删改查、遍历及常用方法还了解了它们在去重、快速查找、键值映射等实际开发场景中的优势除此之外我们还学习了数据容器的一些通用操作并通过综合案例进一步体会了不同数据容器在实际开发中的使用方式。需要注意的是并不存在一种万能的数据容器选择合适的数据结构往往比单纯掌握语法更加重要。只有理解每种数据容器的特点和适用场景才能编写出更加简洁、高效、易维护的代码至此Python 最基础的五种数据容器——列表、元组、字符串、集合和字典已经全部学习完毕。在下一篇文章中我们将开始学习类和对象等语法进一步掌握如何利用 Python 编写更加简洁、优雅且高效的代码