当前位置:首页 > 技术 > 正文内容

Python 集合(Set)数据类型深度解析

访客 技术 2026年10月28日 1

在 Python 中,集合(Set)是一种独特的数据类型,它具有无序性和元素唯一性的特点。这意味着集合中的元素不会重复,并且它们在集合中的顺序是不确定的。集合在处理数学上的集合运算(如并集、交集、差集)以及数据去重等场景中非常实用。

集合的核心特性:可哈希(Hashable)元素

集合中的每个元素都必须是不可变的(immutable)且可哈希的(hashable)。可哈希的数据类型是指其值在生命周期内不可更改,并且可以通过一个哈希函数计算出唯一且稳定的哈希值。这使得集合能够高效地查找和管理元素,类似于字典(Dictionary)的键(Key)。

  • 常见可哈希类型:整数(int)、浮点数(float)、字符串(str)、布尔值(bool)、元组(tuple)。需要注意的是,元组只有在其所有内部元素都是可哈希的情况下,整个元组才可哈希。
  • 常见不可哈希类型:列表(list)、字典(dict)、集合(set)。这些类型是可变的,它们的哈希值可能随时间变化,因此不能作为集合的元素。

创建与元素示例

我们可以使用花括号 {} 来直接创建包含元素的集合。但需要特别注意,{} 如果没有元素,默认创建的是空字典,而非空集合。

# 示例:包含不同类型可哈希元素的集合
my_unique_items = {10, "apple", True, (1, 2, "value")}
print(f"可哈希元素集合: {my_unique_items}")
# 示例输出(顺序不固定):{True, 10, 'apple', (1, 2, 'value')}

# 尝试在集合中包含不可哈希的元素会引发 TypeError
# 以下代码如果运行,将导致错误:
# invalid_set_with_list = {"item_A", [1, 2, 3]} # TypeError: unhashable type: 'list'
# invalid_set_with_dict = {"item_B", {"key": "data"}} # TypeError: unhashable type: 'dict'

# 即使元组中包含不可哈希元素,整个元组也会变得不可哈希
# invalid_tuple_element = {5, (6, [7, 8])} # TypeError: unhashable type: 'list'

在上述例子中,包含列表或字典的尝试都会导致 TypeError,因为集合的元素必须是不可变的。

空集合与单元素集合的创建

创建空集合时,必须使用 set() 函数。

# 创建一个空集合
empty_set = set()
print(f"空集合的类型: {type(empty_set)}") # 输出: <class 'set'>

# 注意:直接使用 {} 会创建一个空字典
empty_dict = {}
print(f"空花括号的类型: {type(empty_dict)}") # 输出: <class 'dict'>

对于只包含一个元素的集合,直接将元素放在花括号中即可,无需额外的逗号。

# 创建一个单元素集合
single_element_set = {"Python"}
print(f"单元素集合: {single_element_set}, 类型: {type(single_element_set)}")
# 输出: {'Python'}, 类型: <class 'set'>

布尔值与整数的等价性

Python 中 True 等价于 1,False 等价于 0。当这些等价的值同时作为集合元素时,由于集合的唯一性原则,只会保留其中一个。具体保留哪个取决于 Python 内部的实现细节和哈希冲突处理,不应依赖其顺序。

# 1 和 True
example_set_1 = {1, True, "value"}
print(f"{{1, True, 'value'}} 的集合: {example_set_1}") # 示例输出: {1, 'value'} 或 {True, 'value'}

example_set_2 = {True, 1, "value"}
print(f"{{True, 1, 'value'}} 的集合: {example_set_2}") # 示例输出: {True, 'value'} 或 {1, 'value'}

# 0 和 False
example_set_3 = {0, False, "test"}
print(f"{{0, False, 'test'}} 的集合: {example_set_3}") # 示例输出: {0, 'test'} 或 {False, 'test'}

example_set_4 = {False, 0, "test"}
print(f"{{False, 0, 'test'}} 的集合: {example_set_4}") # 示例输出: {False, 'test'} 或 {0, 'test'}

为了代码的可读性和可预测性,建议避免在同一个集合中混用这些等价的值。

集合的常见操作方法

添加元素:add()

add() 方法用于向集合中添加一个单一元素。如果该元素已存在,集合不会发生改变。

my_shopping_cart = {"milk", "bread"}
my_shopping_cart.add("eggs")
print(f"添加'eggs'后的购物车: {my_shopping_cart}") # 示例: {'milk', 'bread', 'eggs'}

my_shopping_cart.add("milk") # 'milk'已存在,集合不变
print(f"再次添加'milk'后的购物车: {my_shopping_cart}") # 示例: {'milk', 'bread', 'eggs'}

删除元素:discard() 与 remove()

Python 提供了两种方法来从集合中删除元素,它们在元素不存在时的行为不同:

  • discard(element):删除集合中的指定元素。如果元素不存在,不会引发错误。
  • remove(element):删除集合中的指定元素。如果元素不存在,会引发 KeyError 错误。
programming_languages = {"Python", "Java", "C++", "JavaScript"}
programming_languages.discard("Java") # 删除存在的元素
print(f"discard('Java')后: {programming_languages}") # 示例: {'Python', 'C++', 'JavaScript'}

programming_languages.discard("Ruby") # 删除不存在的元素,不报错
print(f"discard('Ruby')后: {programming_languages}") # 示例: {'Python', 'C++', 'JavaScript'}

programming_languages.remove("C++") # 删除存在的元素
print(f"remove('C++')后: {programming_languages}") # 示例: {'Python', 'JavaScript'}

# programming_languages.remove("Ruby") # 这行会引发 KeyError,因为'Ruby'不存在

批量添加元素:update()

update() 方法可以接受一个可迭代对象(如另一个集合、列表、元组或字符串),将其中的所有元素添加到当前集合中。重复的元素会自动被忽略。

known_frameworks = {"Django", "Flask"}
new_frameworks_list = ["React", "Angular", "Django", "Vue"] # 包含重复项和不同框架

known_frameworks.update(new_frameworks_list)
print(f"update()后框架集合: {known_frameworks}") # 示例: {'Django', 'React', 'Flask', 'Angular', 'Vue'}

# 注意:update() 方法会修改原集合,并且它返回 None。
# 因此,不应将 update() 的结果赋值给一个变量。
# updated_result = known_frameworks.update(["Spring"])
# print(updated_result) # 输出: None

集合的实用应用:数据去重

集合的元素唯一性特性使其成为对列表或其他序列进行去重操作的理想工具。只需将序列转换为集合,再转换回序列即可。

# 原始列表,包含多个重复项
city_list_with_duplicates = ["Beijing", "Shanghai", "Guangzhou", "Shanghai", "Beijing", "Shenzhen"]
print(f"原始列表: {city_list_with_duplicates}")

# 转换为集合进行去重
unique_cities_set = set(city_list_with_duplicates)
print(f"去重后的集合: {unique_cities_set}") # 示例: {'Shanghai', 'Beijing', 'Guangzhou', 'Shenzhen'} (顺序不确定)

# 将去重后的集合转换回列表(如果需要保持列表结构)
deduplicated_city_list = list(unique_cities_set)
print(f"去重后的列表: {deduplicated_city_list}") # 示例: ['Shanghai', 'Beijing', 'Guangzhou', 'Shenzhen'] (顺序不确定)

集合的数学运算

Python 集合提供了丰富的数学集合运算方法和对应的运算符。

交集(Intersection)

交集包含同时存在于两个集合中的所有元素。可以使用 & 运算符或 intersection() 方法。

set_students_math = {"Alice", "Bob", "Charlie", "David"}
set_students_physics = {"Charlie", "David", "Eve", "Frank"}

# 使用 & 运算符
common_students_op = set_students_math & set_students_physics
print(f"数学和物理的交集 (运算符): {common_students_op}") # 输出: {'Charlie', 'David'}

# 使用 intersection() 方法
common_students_method = set_students_math.intersection(set_students_physics)
print(f"数学和物理的交集 (方法): {common_students_method}") # 输出: {'Charlie', 'David'}

并集(Union)

并集包含存在于任一集合中的所有唯一元素。可以使用 | 运算符或 union() 方法。

set_english_speakers = {"John", "Sarah", "Emily"}
set_spanish_speakers = {"Sarah", "Miguel", "Emily"}

# 使用 | 运算符
all_speakers_op = set_english_speakers | set_spanish_speakers
print(f"英语和西班牙语的并集 (运算符): {all_speakers_op}") # 示例: {'John', 'Sarah', 'Emily', 'Miguel'}

# 使用 union() 方法
all_speakers_method = set_english_speakers.union(set_spanish_speakers)
print(f"英语和西班牙语的并集 (方法): {all_speakers_method}") # 示例: {'John', 'Sarah', 'Emily', 'Miguel'}

差集(Difference)

差集包含在一个集合中存在,但在另一个集合中不存在的所有元素。可以使用 - 运算符或 difference() 方法。差集运算是有方向性的。

all_fruits = {"apple", "banana", "cherry", "date"}
eaten_fruits = {"banana", "date", "grape"}

# 在 all_fruits 中但不在 eaten_fruits 中的
remaining_fruits_op = all_fruits - eaten_fruits
print(f"剩余水果 (运算符): {remaining_fruits_op}") # 输出: {'apple', 'cherry'}

remaining_fruits_method = all_fruits.difference(eaten_fruits)
print(f"剩余水果 (方法): {remaining_fruits_method}") # 输出: {'apple', 'cherry'}

# 在 eaten_fruits 中但不在 all_fruits 中的
unknown_fruits_op = eaten_fruits - all_fruits
print(f"未知的被吃水果 (运算符): {unknown_fruits_op}") # 输出: {'grape'}

对称差集(Symmetric Difference)

对称差集包含在两个集合中,但不同时存在于两个集合中的所有元素(即只存在于其中一个集合的元素)。可以使用 ^ 运算符或 symmetric_difference() 方法。

set_team_a = {"Player1", "Player2", "Player3", "Player4"}
set_team_b = {"Player3", "Player4", "Player5", "Player6"}

# 使用 ^ 运算符
players_unique_to_either_op = set_team_a ^ set_team_b
print(f"A队或B队独有的队员 (运算符): {players_unique_to_either_op}") # 示例: {'Player1', 'Player5', 'Player2', 'Player6'}

# 使用 symmetric_difference() 方法
players_unique_to_either_method = set_team_a.symmetric_difference(set_team_b)
print(f"A队或B队独有的队员 (方法): {players_unique_to_either_method}") # 示例: {'Player1', 'Player5', 'Player2', 'Player6'}
标签: Python

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

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