当前位置:首页 > 随笔 > 正文内容

Python 集合类型深度解析:set 与 frozenset 的核心特性与应用

访客 随笔 2026年5月24日 4

核心概念:可变与不可变集合

在 Python 中,集合(Set)是一种基于哈希表实现的无序且不重复的数据结构。它主要分为两种类型:setfrozenset

  • set(可变集合):支持动态添加和移除元素。由于其内容可变,因此它是不可哈希的(unhashable),不能作为字典的键或另一个集合的元素。主要用于去重和关系运算。
  • frozenset(不可变集合):创建后其元素无法更改。这种不可变性使其具备哈希值,因此可以作为字典的键或嵌套在其他集合中。代价是失去了 add()remove() 等修改方法。

一、 集合的初始化与构建

可以通过内置的工厂函数 set()frozenset() 来创建集合,传入的参数必须是可迭代对象。此外,set 还可以使用花括号 {} 字面量直接创建(注意空集合必须用 set(),因为 {} 会创建空字典)。

# 使用工厂函数创建可变集合
dynamic_set = set(['apple', 'banana', 'cherry', 'apple'])
print(dynamic_set)  # 输出: {'apple', 'cherry', 'banana'} (自动去重)
print(type(dynamic_set))  # 输出: <class 'set'>

# 使用字面量语法创建
literal_set = {'dog', 'cat', 'bird'}
print(literal_set)  # 输出: {'dog', 'cat', 'bird'}

# 创建不可变集合
static_set = frozenset(['red', 'green', 'blue', 'red'])
print(static_set)  # 输出: frozenset({'red', 'green', 'blue'})

二、 状态变更与元素操作

只有 set 允许在创建后修改其内容。frozenset 尝试调用修改方法会抛出 AttributeError

numbers = {10, 20, 30}

# 添加单个元素
numbers.add(40)

# 批量更新元素
numbers.update([50, 60, 20]) 

# 移除元素(若不存在则抛出 KeyError)
numbers.remove(10)

# 安全移除(若不存在则静默忽略)
numbers.discard(99)

# 使用运算符移除
numbers -= {30, 40}

print(numbers)  # 输出: {50, 20, 60}

# 尝试修改不可变集合
frozen_nums = frozenset([1, 2, 3])
# frozen_nums.add(4)  # 触发 AttributeError: 'frozenset' object has no attribute 'add'

三、 成员检测与关系判定

集合提供了高效的成员资格测试以及丰富的数学关系判定。

set_a = {'x', 'y', 'z'}
set_b = frozenset(['x', 'y', 'w'])

# 成员检测
print('x' in set_a)       # True
print('w' not in set_a)   # True

# 等价与不等价测试
print(set_a == set_b)     # False
print(set({'x', 'y'}) != set_a) # True

# 子集与超集判定
print({'x', 'y'} < set_a)        # True (严格子集)
print(set_a >= {'x'})            # True (超集)
print(set_a.issubset({'x', 'y', 'z', 'w'})) # True

四、 遍历集合元素

无论是可变还是不可变集合,都支持迭代协议。由于集合是无序的,遍历输出的顺序可能与插入顺序不同。

colors = frozenset(['cyan', 'magenta', 'yellow'])
for color in colors:
    print(color)
# 输出顺序不固定,例如: yellow, cyan, magenta

五、 数学集合运算

Python 为集合提供了直观的运算符和对应的方法,用于执行标准的数学集合操作。

1. 并集 (Union)

包含两个集合中的所有唯一元素。运算符:|,方法:union()

s1 = {1, 2, 3}
s2 = {3, 4, 5}
print(s1 | s2)         # {1, 2, 3, 4, 5}
print(s1.union(s2))    # {1, 2, 3, 4, 5}

2. 交集 (Intersection)

包含同时存在于两个集合中的元素。运算符:&,方法:intersection()

print(s1 & s2)              # {3}
print(s1.intersection(s2))  # {3}

3. 差集 (Difference)

包含在第一个集合中但不在第二个集合中的元素。运算符:-,方法:difference()

print(s1 - s2)              # {1, 2}
print(s1.difference(s2))    # {1, 2}

4. 对称差集 (Symmetric Difference)

包含只属于其中一个集合的元素(排除交集部分)。运算符:^,方法:symmetric_difference()

print(s1 ^ s2)                        # {1, 2, 4, 5}
print(s1.symmetric_difference(s2))    # {1, 2, 4, 5}

5. 混合类型运算的返回规则

setfrozenset 混合进行运算时,返回结果的类型由左操作数决定。

mutable = {1, 2}
immutable = frozenset([2, 3])

print(type(mutable | immutable))   # <class 'set'>
print(type(immutable | mutable))   # <class 'frozenset'>

六、 核心方法与操作符速查表

通用方法与操作符(适用于 set 和 frozenset)

操作/方法 等价运算符 功能描述
len(s)-返回集合中元素的数量
obj in s-判断 obj 是否存在于 s 中
obj not in s-判断 obj 是否不存在于 s 中
s == t==判断两个集合是否包含完全相同的元素
s < t<严格子集测试(s 是 t 的子集且 s != t)
s.issubset(t)<=子集测试(允许 s == t)
s > t>严格超集测试
s.issuperset(t)>=超集测试(允许 s == t)
s.union(t, ...)|返回多个集合的并集
s.intersection(t, ...)&返回多个集合的交集
s.difference(t, ...)-返回差集
s.symmetric_difference(t)^返回对称差集
s.copy()-返回集合的浅拷贝

可变集合专属方法(仅适用于 set)

方法 等价运算符 功能描述
s.update(t, ...)|=将其他集合或可迭代对象中的元素合并到 s 中
s.intersection_update(t, ...)&=仅保留 s 与其他集合共有的元素
s.difference_update(t, ...)-=从 s 中移除也存在于其他集合中的元素
s.symmetric_difference_update(t)^=更新 s 为对称差集
s.add(elem)-向集合中添加单个元素
s.remove(elem)-移除指定元素,若不存在则抛出 KeyError
s.discard(elem)-移除指定元素,若不存在则不执行任何操作
s.pop()-随机移除并返回一个元素,若集合为空则抛出 KeyError
s.clear()-清空集合中的所有元素
标签: Pythonset

相关文章

可以按小时收费的VPS

很多 VPS 提供商都支持 按小时计费(hourly billing),想短期试用 / 临时搭建节点、测试网络、短期项目等场景非常合适。下面是当前最主流且靠谱的按小时 VPS 选项,分别按不同需求场景整理: 1. Vultr(全球节点,包括日本) 按小时计费 可选机房:东京 / 大阪 / 洛杉矶 / 法兰克福 / 伦敦 … 支持 PayPal(部分情况),但更常用信用卡/PayPal+卡价格参考$...

在 iPhone 上下载国外App

地区/国家限制App Store 会根据 Apple ID 的国家或地区限制应用下载。如果你的 Apple ID 绑定的是中国大陆,就可能无法下载 OpenAI 官方的 ChatGPT 应用,因为它在大陆 App Store 不上架。解决办法:换成美国、加拿大、香港等地区的 Apple ID。或者在现有 Apple ID 上更改地区。注册一个国外 Apple ID(推荐)比如注册 美国区 Appl...

Node.js 中的异步编程:回调与 Promise

Node.js 是一个基于 JavaScript 构建的单线程、非阻塞运行环境,它通过异步编程机制来高效处理多个操作。在执行如文件读取、API 请求或数据库查询等任务时,Node.js 不会等待这些操作完成,而是使用回调函数和 Promise 来避免阻塞主线程。 回调方式实现异步 那么当异步操作完成后,Node.js 如何知道接下来要做什么呢?这就要用到 回调函数(callback)。 回调本质上...

Selenium自动化测试入门指南

Selenium自动化测试入门指南

什么是自动化测试? 自动化测试是指利用软件工具自动执行测试用例,模拟用户操作,如打开网页、点击链接、输入文本等,并验证结果是否符合预期。 其主要优点包括: 大幅减少人工成本 测试速度快 可以在非工作时间运行 支持持续集成和交付 然而,它也存在一些局限性,例如开发成本较高、不适合快速变化的项目、依赖稳定的UI界面等。 自动化测试的应用条件 适合引入自动化测试的情况包括: 手动测试耗时且需要大量...

MariaDB Galera集群故障快速恢复指南

OpenStack控制节点采用三节点MariaDB Galera集群架构。当数据库集群因故障重启时,有时会出现Galera集群无法正常启动的问题。虽然有多种方法可以恢复数据库服务,但如何实现快速启动同时确保数据完整性呢? 通过分析日志发现,MariaDB Galera集群节点宕机时会在日志中输出以下信息: [Note] WSREP: 新集群视图:全局状态: 874d8e7e-5980-11e8-8...

Android 中 EventBus 的通信机制与实现原理深度解析

EventBus 核心设计思想 EventBus 是一个基于观察者模式的事件总线框架,广泛应用于 Android 平台以实现组件解耦。它通过中心化的消息分发机制,使不同层级、不同线程的对象能够以"发布-订阅"方式通信,避免了传统接口回调或广播带来的强依赖问题。 核心角色说明 事件(Event):任意 Java 对象,作为数据载体,如网络状态变更通知、用户登录信息等。 发布者(Publi...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。