程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Python 基础

    • 环境搭建
    • 标识符
    • 变量
    • 缩进和注释
    • 数据类型
    • 数据类型转换
    • 运算符
    • 字符串
    • 列表
    • 元组
    • 字典
    • 集合
      • 1. 什么是集合 (Set)?
      • 2. 创建集合
        • 2.1 使用花括号 {}
        • 2.2 使用 set() 构造函数
        • 2.3 创建空集合
      • 3. 集合的基本操作
        • 3.1 添加元素
        • 3.2 删除元素
      • 4. 强大的集合运算
        • 4.1 并集 (Union)
        • 4.2 交集 (Intersection)
        • 4.3 差集 (Difference)
        • 4.4 对称差集 (Symmetric Difference)
      • 5. 子集与超集判断
      • 6. 原地更新运算 (In-place Updates)
        • 6.1 并集更新
        • 6.2 交集更新
        • 6.3 差集更新
        • 6.4 对称差集更新
      • 7. 遍历与推导式
        • 7.1 遍历集合
        • 7.2 集合推导式 (Set Comprehension)
      • 8. 不可变集合:frozenset
      • 9. 总结与最佳实践
    • if判断
    • for循环
    • while循环
    • 循环综合练习
    • Python函数
    • 函数与循环实战
    • 生成式
    • 文件读写
    • 面向对象
    • 面向对象综合案例
  • Python 进阶

  • Python
  • Python 基础
scholar
2025-07-20
目录

集合

# 集合 (Set)

集合(Set)是 Python 中一种非常重要的数据结构,它源自数学中的集合概念。想象一个袋子,你只能往里面放独一无二的物品,而且袋子里的物品是杂乱无章的——这就是集合的精髓。


# 1. 什么是集合 (Set)?

集合是一个无序 (Unordered)、不重复 (Unique) 的元素集合。

  • 无序性:集合中的元素没有固定的顺序。你放入的顺序不代表取出的顺序,因此集合不支持索引 [0] 或切片操作。
  • 唯一性:集合会自动去除所有重复的元素,确保每个元素只出现一次。
  • 可变性 (Mutable):你可以随时向集合中添加或删除元素(对于常规的 set)。
  • 元素要求:集合中的元素必须是不可变类型,例如:int, float, str, tuple。列表 list、字典 dict 和其他集合 set 等可变类型不能作为集合的元素。

# 2. 创建集合

Python 提供了多种方式来创建集合。

# 2.1 使用花括号 {}

这是创建非空集合最直接的方式。

# 创建一个包含元素的集合,重复的元素会被自动忽略
fruits = {"apple", "banana", "cherry", "apple"}
print(f"创建的集合: {fruits}") # 输出: 创建的集合: {'banana', 'cherry', 'apple'} (注意:顺序可能不同)
1
2
3

# 2.2 使用 set() 构造函数

set() 函数可以将任何可迭代对象(如列表、元组、字符串)转换为集合,这是去重的最佳方式。

# 从列表创建集合 (自动去重)
my_list = [1, 2, 3, 2, 1]
my_set_from_list = set(my_list)
print(f"从列表创建: {my_set_from_list}") # 输出: 从列表创建: {1, 2, 3}

# 从字符串创建集合
my_set_from_str = set("hello")
print(f"从字符串创建: {my_set_from_str}") # 输出: 从字符串创建: {'e', 'o', 'l', 'h'}

# 从元组创建集合
my_tuple = (10, 20, 30)
my_set_from_tuple = set(my_tuple)
print(f"从元组创建: {my_set_from_tuple}") # 输出: 从元组创建: {10, 20, 30}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 2.3 创建空集合

新手陷阱:创建一个空集合必须使用 set() 函数,因为 {} 在 Python 中用于创建空字典。

# 正确方式
empty_set = set()
print(f"空集合: {empty_set}, 类型: {type(empty_set)}") # 输出: 空集合: set(), 类型: <class 'set'>

# 错误方式
empty_dict = {}
print(f"空对象: {empty_dict}, 类型: {type(empty_dict)}") # 输出: 空对象: {}, 类型: <class 'dict'>
1
2
3
4
5
6
7

# 3. 集合的基本操作

# 3.1 添加元素

  • add(element): 向集合中添加单个元素。如果元素已存在,则不做任何操作。
  • update(iterable): 将一个可迭代对象中的所有元素批量添加到集合中。
skills = {"Python", "Java"}
print(f"初始集合: {skills}") # 输出: 初始集合: {'Python', 'Java'}

# 添加单个元素
skills.add("Go")
print(f"add('Go') 后: {skills}") # 输出: add('Go') 后: {'Java', 'Go', 'Python'}

# 再次添加已存在的元素,集合不变
skills.add("Java")
print(f"add('Java') 后: {skills}") # 输出: add('Java') 后: {'Java', 'Go', 'Python'}

# 批量添加多个元素
skills.update(["C++", "SQL"])
print(f"update(['C++', 'SQL']) 后: {skills}") # 输出: ... {'SQL', 'Java', 'Go', 'C++', 'Python'}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 3.2 删除元素

  • remove(element): 删除指定的元素。如果元素不存在,会抛出 KeyError 异常。
  • discard(element): 删除指定的元素。如果元素不存在,它会静默处理,不会报错。
  • pop(): 随机删除并返回一个元素。对空集合使用 pop() 会抛出 KeyError。
  • clear(): 清空集合中的所有元素。
members = {"Alice", "Bob", "Charlie", "David"}
print(f"初始集合: {members}") # 输出: 初始集合: {'David', 'Charlie', 'Bob', 'Alice'}

# 使用 remove 删除存在的元素
members.remove("Bob")
print(f"remove('Bob') 后: {members}") # 输出: remove('Bob') 后: {'David', 'Charlie', 'Alice'}

# 使用 discard 删除不存在的元素 (安全)
members.discard("Eve") # 不会报错
print(f"discard('Eve') 后: {members}") # 输出: discard('Eve') 后: {'David', 'Charlie', 'Alice'}

# 尝试用 remove 删除不存在的元素 (会报错)
try:
    members.remove("Frank")
except KeyError:
    print("用 remove 删除 'Frank' 失败,因为它不存在。") # 输出: 用 remove 删除 'Frank' 失败,因为它不存在。

# 随机弹出一个元素
popped_member = members.pop()
print(f"被 pop 的成员: {popped_member}") # 输出: 被 pop 的成员: David (或其他任意一个)
print(f"pop() 后的集合: {members}") # 输出: pop() 后的集合: {'Charlie', 'Alice'}

# 清空集合
members.clear()
print(f"clear() 后的集合: {members}") # 输出: clear() 后的集合: set()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 4. 强大的集合运算

集合最强大的功能在于其丰富的数学运算,可以高效地处理数据关系。

# 准备两个集合
frontend_skills = {"HTML", "CSS", "JavaScript"}
backend_skills = {"Python", "SQL", "JavaScript"}
1
2
3

# 4.1 并集 (Union)

获取两个集合中的所有元素,并自动去重。

  • 运算符: |
  • 方法: .union()
# 并集
all_skills_op = frontend_skills | backend_skills
all_skills_method = frontend_skills.union(backend_skills)

print(f"并集 (运算符): {all_skills_op}") # 输出: ... {'CSS', 'JavaScript', 'SQL', 'HTML', 'Python'}
print(f"并集 (方法): {all_skills_method}") # 输出: ... {'CSS', 'JavaScript', 'SQL', 'HTML', 'Python'}
1
2
3
4
5
6

# 4.2 交集 (Intersection)

获取两个集合中共同存在的元素。

  • 运算符: &
  • 方法: .intersection()
# 交集
common_skills_op = frontend_skills & backend_skills
common_skills_method = frontend_skills.intersection(backend_skills)

print(f"交集 (运算符): {common_skills_op}") # 输出: 交集 (运算符): {'JavaScript'}
print(f"交集 (方法): {common_skills_method}") # 输出: 交集 (方法): {'JavaScript'}
1
2
3
4
5
6

# 4.3 差集 (Difference)

获取存在于第一个集合但不存在于第二个集合的元素。

  • 运算符: -
  • 方法: .difference()
# 差集
frontend_only_op = frontend_skills - backend_skills
backend_only_method = backend_skills.difference(frontend_skills)

print(f"只会前端的技能: {frontend_only_op}") # 输出: 只会前端的技能: {'HTML', 'CSS'}
print(f"只会后端的技能: {backend_only_method}") # 输出: 只会后端的技能: {'SQL', 'Python'}
1
2
3
4
5
6

# 4.4 对称差集 (Symmetric Difference)

获取只存在于其中一个集合,但不是两个集合共有的元素。

  • 运算符: ^
  • 方法: .symmetric_difference()
# 对称差集
exclusive_skills_op = frontend_skills ^ backend_skills
exclusive_skills_method = frontend_skills.symmetric_difference(backend_skills)

print(f"非共有技能 (运算符): {exclusive_skills_op}") # 输出: ... {'SQL', 'Python', 'HTML', 'CSS'}
print(f"非共有技能 (方法): {exclusive_skills_method}") # 输出: ... {'SQL', 'Python', 'HTML', 'CSS'}
1
2
3
4
5
6

# 5. 子集与超集判断

  • 子集 (Subset): A.issubset(B) 或 A <= B,判断集合 A 的所有元素是否都在集合 B 中。
  • 超集 (Superset): A.issuperset(B) 或 A >= B,判断集合 A 是否包含集合 B 的所有元素。
  • 真子集/真超集: 使用 < 和 > 判断,要求是子集/超集且两个集合不相等。
  • 不相交 (Disjoint): A.isdisjoint(B),判断两个集合是否没有任何共同元素。
A = {1, 2, 3}
B = {1, 2, 3, 4, 5}
C = {1, 2}
D = {10, 20}

# 子集判断
print(f"A 是 B 的子集吗? {A.issubset(B)}") # 输出: A 是 B 的子集吗? True
print(f"C <= A: {C <= A}") # 输出: C <= A: True

# 超集判断
print(f"B 是 A 的超集吗? {B.issuperset(A)}") # 输出: B 是 A 的超集吗? True
print(f"B >= C: {B >= C}") # 输出: B >= C: True

# 真子集判断
print(f"A 是 B 的真子集吗? {A < B}") # 输出: A 是 B 的真子集吗? True
print(f"A < A: {A < A}")           # 输出: A < A: False

# 不相交判断
print(f"A 和 D 是否不相交? {A.isdisjoint(D)}") # 输出: A 和 D 是否不相交? True
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 6. 原地更新运算 (In-place Updates)

与第4节的运算不同,这些运算会直接修改调用它们的集合本身,而不是返回一个新集合。它们通常在处理大型集合时更高效,因为避免了创建新对象的开销。

# 6.1 并集更新

  • 运算符: |=
  • 方法: update() (已在3.1中介绍)
set1 = {1, 2, 3}
set2 = {3, 4, 5}
set1 |= set2  # 等价于 set1.update(set2)
print(f"并集更新后: {set1}") # 输出: 并集更新后: {1, 2, 3, 4, 5}
1
2
3
4

# 6.2 交集更新

  • 运算符: &=
  • 方法: .intersection_update()
set1 = {1, 2, 3}
set2 = {3, 4, 5}
set1.intersection_update(set2)
print(f"交集更新后: {set1}") # 输出: 交集更新后: {3}
1
2
3
4

# 6.3 差集更新

  • 运算符: -=
  • 方法: .difference_update()
set1 = {1, 2, 3}
set2 = {3, 4, 5}
set1 -= set2 # 等价于 set1.difference_update(set2)
print(f"差集更新后: {set1}") # 输出: 差集更新后: {1, 2}
1
2
3
4

# 6.4 对称差集更新

  • 运算符: ^=
  • 方法: .symmetric_difference_update()
set1 = {1, 2, 3}
set2 = {3, 4, 5}
set1.symmetric_difference_update(set2)
print(f"对称差集更新后: {set1}") # 输出: 对称差集更新后: {1, 2, 4, 5}
1
2
3
4

# 7. 遍历与推导式

# 7.1 遍历集合

可以使用 for 循环遍历集合中的每一个元素,但请记住,遍历的顺序是不确定的。

fruits = {"apple", "banana", "cherry"}
print("--- 遍历集合 ---")
for fruit in fruits:
    print(fruit)
# 可能的输出 (顺序不保证):
# cherry
# banana
# apple
1
2
3
4
5
6
7
8

# 7.2 集合推导式 (Set Comprehension)

这是一种简洁、高效地创建集合的方式,语法与列表推导式非常相似。

# 创建一个包含 0 到 9 中偶数的平方的集合
squares = {x**2 for x in range(10) if x % 2 == 0}
print(squares) # 输出: {0, 64, 4, 36, 16}
1
2
3

# 8. 不可变集合:frozenset

frozenset 是 set 的不可变版本。一旦创建,就不能再添加或删除任何元素。

  • 为什么需要它? 因为集合的元素必须是不可变的,所以普通的 set 不能作为另一个 set 的元素,也不能作为字典的键。frozenset 正好解决了这个问题。
# 创建 frozenset
frozen_skills = frozenset(["Python", "Java"])
print(frozen_skills) # 输出: frozenset({'Java', 'Python'})

# 尝试修改会报错
# frozen_skills.add("Go")  # AttributeError: 'frozenset' object has no attribute 'add'

# 主要用途:作为字典的键
team_skills = {
    frozenset({"Python", "SQL"}): "后端团队",
    frozenset({"HTML", "CSS", "JavaScript"}): "前端团队"
}
print(team_skills[frozenset({"Python", "SQL"})]) # 输出: 后端团队
1
2
3
4
5
6
7
8
9
10
11
12
13

frozenset 支持所有不修改自身的集合操作,如 .union(), .intersection(), in 判断等。


# 9. 总结与最佳实践

  • 核心应用场景:
    1. 高效去重:将列表或其他可迭代对象转换为 set 是最快、最简洁的去重方法。
    2. 快速成员资格测试:判断一个元素是否在一个集合中 (element in my_set) 的速度远快于在列表中查找,尤其是在数据量大时。
  • 性能对比:
    • set 的成员资格测试平均时间复杂度为 O(1)。
    • list 的成员资格测试平均时间复杂度为 O(n)。这意味着列表越大,查找越慢。
  • 何时选择 set:
    • 当你需要存储一系列唯一的项时。
    • 当你关心的是元素是否存在,而不是它们的顺序时。
    • 当你需要频繁进行数据去重或数学集合运算时。
编辑此页 (opens new window)
上次更新: 2025/07/23, 06:33:16
字典
if判断

← 字典 if判断→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式