在本篇教程中,你将深入学习 Python 集合的基础知识,以及各种能够修改 Python 集合的方法。
集合是 Python 内置的数据结构之一。 当你需要处理一组不包含重复元素的集合时,集合是你的首选数据结构。
接下来的内容里,我们将探讨 Python 集合的基本概念和相关操作方法。 然后,我们将学习如何在 Python 中执行常见的集合运算。
让我们开始吧!
Python 集合的基础概念
在 Python 中,集合是一个无序且元素不重复的集合。 这意味着集合内的所有元素都必须是唯一的。
你可以向集合中添加或删除元素; 因此,集合属于可变类型。 它能容纳不同类型的数据。 然而,集合中的每个元素都必须是可哈希的.
在 Python 中,如果一个对象的哈希值在其生命周期内保持不变,我们称该对象是可哈希的。 大部分不可变对象(如 Python 字符串、元组和数值)都符合可哈希的要求。
我们将详细探讨如何创建集合。 现在,请看以下两组示例:
py_set = {0,1,2,(2,3,4),'Cool!'} py_set = {0,1,2,[2,3,4],'Oops!'} # 输出 --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-40-2d3716c7fe01> in <module>() ----> 1 py_set = {0,1,2,[2,3,4],'Oops!'} TypeError: unhashable type: 'list'
第一组示例包含三个数字,一个元组和一个字符串。 集合初始化操作顺利完成。 而第二组示例中,用列表替代了元组。 列表是可变的,不能被哈希,因此初始化时抛出了一个 TypeError。
总而言之,我们可以将 Python 集合定义为包含不同且可哈希元素的可变集合。
如何创建 Python 集合
我们从学习如何在 Python 中创建集合开始。
#1. 使用显式初始化
在 Python 中,你可以通过明确列出集合的元素来创建集合,这些元素用逗号 (,) 分隔,并用一对花括号 {} 包裹。
py_set1 = {'Python','C','C++','JavaScript'} type(py_set1) # 输出 set
如果你使用过 Python 列表,你会知道使用 [] 可以初始化一个空列表。 虽然 Python 集合也使用花括号 {} 来表示,但是你不能用一对空的花括号 {} 来初始化一个空集合。 因为 {} 初始化的是 Python 字典而不是 Python 集合。
py_set2 = {} type(py_set2) # 输出 dict
你可以再次调用 `type()` 函数来确认 `py_set2` 是一个字典(dict)。
#2. 使用 set() 函数
如果你需要初始化一个空集合,然后逐步添加元素,可以使用 `set()` 函数。
py_set3 = set() type(py_set3) # 输出 set
#3. 将其他可迭代对象转换为集合
创建集合的另一种方法是使用 `set(iterable)` 函数,将如列表或元组等可迭代对象转换为集合。
py_list = ['Python','C','C++','JavaScript','C'] py_set4 = set(py_list) print(py_set4) # {'C++', 'C', 'JavaScript', 'Python'} # 重复元素 'C' 被移除 type(py_set4) # set
在上面的例子中,`py_list` 包含两次 “C”。 但是在 `py_set4` 中,”C” 只出现一次,因为集合中不允许存在重复元素。 这种转换成集合的方法常被用来从 Python 列表中去除重复项。
如何向 Python 集合添加元素
首先,让我们创建一个空集合 `py_set`,并在接下来的内容中使用它。
py_set = set() len(py_set) # 返回集合的长度 # 输出 0
#1. 使用 .add() 方法
要向集合中添加元素,可以使用 `.add()` 方法。 `set.add(element)` 可以将元素添加到集合中。
为了清晰起见,我们将逐步向 Python 集合添加元素,并打印出每一步的集合状态。
▶️ 让我们向 `py_set` 添加字符串 “Python”。
py_set.add('Python') print(py_set) # 输出 {'Python'}
接下来,我们添加另一个元素。
py_set.add('C++') print(py_set) # 输出 {'Python', 'C++'}
务必理解,`.add()` 方法只有在元素不存在时才会将其添加到集合中。 如果集合中已经包含了你想要添加的元素,添加操作将不会有任何效果。
为了验证这一点,我们尝试再次向 `py_set` 中添加 “C++”。
py_set.add('C++') print(py_set) # 输出 {'Python', 'C++'}
集合中已经存在 “C++”,因此添加操作不起作用。
▶️ 让我们在集合中添加更多元素。
py_set.add('C') print(py_set) py_set.add('JavaScript') print(py_set) py_set.add('Rust') print(py_set) # 输出 {'Python', 'C++', 'C'} {'JavaScript', 'Python', 'C++', 'C'} {'Rust', 'JavaScript', 'Python', 'C++', 'C'}
#2. 使用 .update() 方法
目前为止,我们已经学习了如何向现有的集合中添加元素 — 每次一个元素。
如果你想要一次性添加多个元素呢?
你可以使用 `.update()` 方法,其语法是:`set.update(collection)`。 这个方法可以将一个集合中的所有元素添加到另一个集合中。 这里的 “collection” 可以是列表、元组、字典等。
py_set.update(['Julia','Ruby','Scala','Java']) print(py_set) # 输出 {'C', 'C++', 'Java', 'JavaScript', 'Julia', 'Python', 'Ruby', 'Rust', 'Scala'}
当你想要将一组元素添加到集合中,并且不想在内存中创建新的对象时,这个方法非常有用。
下一节,我们将学习如何从集合中移除元素。
如何从 Python 集合中移除元素
我们以以下集合(在执行更新操作之前的 `py_set`)为例。
py_set = {'C++', 'JavaScript', 'Python', 'Rust', 'C'}
#1. 使用 .pop() 方法
`set.pop()` 方法从集合中随机删除并返回一个元素。 让我们在 `py_set` 上调用 `pop` 方法,看看它返回了什么。
py_set.pop() # 输出 'Rust'
这一次,调用 `.pop()` 方法返回了字符串 “Rust”。
注意:因为 `.pop()` 方法会随机返回一个元素,你最后运行时可能得到不同的元素。
当我们查看集合时,”Rust” 已经不在其中了。
print(py_set) # 输出 {'JavaScript', 'Python', 'C++', 'C'}
#2. 使用 .remove() 和 .discard() 方法
在实际应用中,你可能希望从集合中移除特定的元素。 你可以使用 `.remove()` 和 `.discard()` 方法来实现这一点。
`set.remove(element)` 方法可以从集合中移除指定的元素。
py_set.remove('C') print(py_set) # 输出 {'JavaScript', 'Python', 'C++'}
如果我们尝试移除集合中不存在的元素,会遇到 `KeyError` 错误。
py_set.remove('Scala') # 输出 --------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-58-a1abab3a8892> in <module>() ----> 1 py_set.remove('Scala') KeyError: 'Scala'
让我们再次查看 `py_set`。现在,它包含三个元素。
print(py_set) # 输出 {'JavaScript', 'Python', 'C++'}
使用语法 `set.discard(element)`,`.discard()` 方法也能从集合中移除元素。
py_set.discard('C++') print(py_set) # 输出 {'JavaScript', 'Python'}
它与 `.remove()` 方法的不同之处在于:当我们尝试删除不存在的元素时,它不会抛出 `KeyError` 错误。
如果我们尝试使用 `.discard()` 方法从列表中删除 “Scala”(不存在的元素),我们不会看到任何错误。
py_set.discard('Scala') # 不会报错! print(py_set) # 输出 {'JavaScript', 'Python'}
如何访问 Python 集合的元素
目前为止,我们已经学习了如何在 Python 集合中添加和移除元素。 但是,我们还没有了解如何访问集合中的单个元素。
由于集合是一个无序的集合,因此它不支持索引。 如果你尝试通过索引来访问集合中的元素,你会遇到错误,如下所示。
py_set = {'C++', 'JavaScript', 'Python', 'Rust', 'C'} print(py_set[0]) # 输出 --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-27-0329274f4580> in <module>() ----> 1 print(py_set[0]) TypeError: 'set' object is not subscriptable
那么如何访问集合中的元素呢?
有两种常用的方法可以做到这一点:
- 遍历集合并访问每个元素
- 检查特定元素是否是集合的成员
▶️ 使用 for 循环遍历集合并访问元素。
for elt in py_set: print(elt) # 输出 C++ JavaScript Python Rust C
在实践中,你可能希望使用 `in` 运算符来检查给定的元素是否存在于集合中。
注意:如果元素存在于集合中,则 `in` 运算符返回 True;否则返回 False。
在这个示例中,`py_set` 包含 “C++”,但不包含 “Julia”。`in` 运算符分别返回 True 和 False。
'C++' in py_set # True 'Julia' in py_set # False
如何获取 Python 集合的长度
如前所述,你可以使用 `len()` 函数来获取集合中元素的数量。
py_set = {'C++', 'JavaScript', 'Python', 'Rust', 'C'} len(py_set) # 输出: 5
如何清空 Python 集合
要移除所有元素清空集合,你可以使用 `.clear()` 方法。
让我们在 `py_set` 上调用 `.clear()` 方法。
py_set.clear()
如果你尝试打印它,你将得到 `set()`,这表明该集合是空的。 你还可以调用 `len()` 函数来确认集合的长度为零。
print(py_set) # set() print(len(py_set)) # 0
目前为止,我们已经学习了如何在 Python 集合上执行基本的 CRUD 操作:
- 创建:使用 `set()` 函数,类型转换和初始化
- 读取:使用循环和 `in` 运算符访问集合中的元素进行成员资格测试
- 更新:在集合中添加、移除元素和更新集合
- 删除:通过移除集合中的所有元素来清空集合
使用 Python 代码解释常见的集合运算
Python 集合也允许我们执行基本的集合运算。 我们将在本节中学习这些运算。
#1. Python 中的集合并集
在集合论中,两个集合的并集是包含两个集合中所有元素的集合。 如果有两个集合 A 和 B,它们的并集包含只存在于 A 中的元素,只存在于 B 中的元素,以及同时存在于 A 和 B 中的元素。
要查找集合的并集,你可以使用 `|` 运算符或 `.union()` 方法。语法是:`setA.union(setB)`。
setA = {1,3,5,7,9} setB = {2,4,6,8,9} print(setA | setB) # 输出 {1, 2, 3, 4, 5, 6, 7, 8, 9} setA.union(setB) # 输出 {1, 2, 3, 4, 5, 6, 7, 8, 9}
集合的并集运算是可交换的; 所以 AUB 与 BUA 相同。 让我们通过在 `.union()` 方法中交换 `setA` 和 `setB` 的位置来验证这一点。
setB.union(setA) # 输出 {1, 2, 3, 4, 5, 6, 7, 8, 9}
#2. Python 中的集合交集
另一个集合运算是两个集合 A 和 B 的交集。 集合的交集运算返回一个集合,其中包含 A 和 B 中都存在的元素。
要计算交集,你可以使用 `&` 运算符或者 `.intersection()` 方法,如下面的代码片段所示。
print(setA & setB) # 输出 {9} setA.intersection(setB) # 输出 {9}
在这个例子中,元素 9 同时存在于 `setA` 和 `setB` 中;因此,交集只包含这个元素。
和集合的并集一样,集合的交集运算也是可交换的。
setB.intersection(setA) # 输出 {9}
#3. Python 中的集合差集
对于任意两个集合,并集和交集分别帮助我们找到这两个集合中存在的元素和至少在一个集合中存在的元素。 另一方面,集合差集帮助我们找到存在于一个集合中,但不存在于另一个集合中的元素。
– `setA.difference(setB)` 给出只存在于 `setA` 中,而不存在于 `setB` 中的元素集合。
– `setB.difference(setA)` 给出只存在于 `setB` 中,而不存在于 `setA` 中的元素集合。
print(setA - setB) print(setB - setA) # 输出 {1, 3, 5, 7} {8, 2, 4, 6}
很明显,A-B 与 B-A 不同,因此集合差集运算不是可交换的。
setA.difference(setB) # {1, 3, 5, 7} setB.difference(setA) # {2, 4, 6, 8}
#4. Python 中的对称集合差集
尽管集合的交集为我们提供了两个集合中都存在的元素,但对称集合差集返回恰好存在于其中一个集合中的元素的集合。
考虑以下示例。
setA = {1,3,5,7,10,12} setB = {2,4,6,8,10,12}
要计算对称差集,你可以使用 `^` 运算符或者 `.symmetric_difference()` 方法。
print(setA ^ setB) # 输出 {1, 2, 3, 4, 5, 6, 7, 8}
元素 10 和 12 存在于 `setA` 和 `setB` 中。因此它们不会出现在对称差集中。
setA.symmetric_difference(setB) # 输出 {1, 2, 3, 4, 5, 6, 7, 8}
由于对称集合差集运算会收集恰好存在于两个集合之一中的所有元素,因此,无论元素收集的顺序如何,结果集合都相同。 因此,对称集合差集运算是可交换的。
setB.symmetric_difference(setA) # 输出 {1, 2, 3, 4, 5, 6, 7, 8}
#5. Python 中的子集和超集
在集合论中,子集和超集的概念有助于理解两个集合之间的关系。
给定两个集合 A 和 B,如果集合 B 中的所有元素也都存在于集合 A 中,则集合 B 是集合 A 的子集。 而集合 A 是集合 B 的超集。
考虑两个集合的例子:编程语言和编程语言扩展。
languages = {'Python', 'JavaScript','C','C++'} languages_extended = {'Python', 'JavaScript','C','C++','Rust','Go','Scala'}
在 Python 中,你可以使用 `.issubset()` 方法来检查一个给定的集合是否是另一个集合的子集。
如果 `setA` 是 `setB` 的子集,`setA.issubset(setB)` 返回 True;否则,返回 False。
在这个例子中,`languages` 是 `languages_extended` 的子集。
languages.issubset(languages_extended) # 输出 True
类似地,你可以使用 `.issuperset()` 方法来检查一个给定的集合是否是另一个集合的超集。
如果 `setA` 是 `setB` 的超集,`setA.issuperset(setB)` 返回 True;否则,返回 False。
languages_extended.issuperset(languages) # 输出 True
由于 `languages_extended` 是 `languages` 的超集,如上所示, `languages_extended.issuperset(languages)` 返回 True。
结论
希望本教程能够帮助你了解 Python 集合的工作方式,以及集合的 CRUD 操作、集合方法和常见集合运算。 下一步,你可以尝试在 Python 项目中使用它们。
你也可以查看其他深入的 Python 指南。 祝你学习愉快!