Python3 集合
Python3 集合 集合(Set)是 Python 中的一种内置容器类型,用于存储多个不重复的元素。 集合具有以下特点: 元素不重复:相同的元素只会保留一份。 无序:元素没有固定的排列顺序,不支持通过索引访问。
集合(Set)是 Python 中的一种内置容器类型,用于存储多个不重复的元素。
集合具有以下特点:
- 元素不重复:相同的元素只会保留一份。
- 无序:元素没有固定的排列顺序,不支持通过索引访问。
- 元素必须可哈希:可以包含整数、字符串、元组等符合条件的对象,但不能直接包含列表、字典等不可哈希对象。
- 支持集合运算:可以进行并集、交集、差集、对称差集等操作。
- 可以修改:普通
set支持添加和删除元素。
集合常用于数据去重、成员判断以及多个数据集合之间的比较。
创建集合
可以使用大括号 {} 创建非空集合,元素之间使用逗号分隔,也可以使用 set() 从可迭代对象创建集合。
语法格式:
set_name = {value1, value2, value3}
set_name = set(iterable)
例如:
实例
set1 = {1, 2, 3, 4}
# 使用 set() 从列表创建集合
set2 = set([4, 5, 6, 7])
# 从字符串创建集合
set3 = set("hello")
print(sorted(set1))
print(sorted(set2))
print(sorted(set3))
执行结果:
[1, 2, 3, 4] [4, 5, 6, 7] ['e', 'h', 'l', 'o']
可以看到,set("hello") 自动去除了重复的字母 l。
注意:创建空集合必须使用 set(),不能使用 {},因为 {} 表示空字典。
empty_set = set() # 空集合
empty_dict = {} # 空字典
print(type(empty_set))
print(type(empty_dict))
执行结果:
<class 'set'> <class 'dict'>
集合自动去重
集合中的元素不会重复,因此可以利用 set() 对列表等可迭代对象进行去重。
实例
unique_numbers = set(numbers)
print(sorted(unique_numbers))
执行结果:
[1, 2, 3, 4, 5]
需要注意,转换为集合后,原有元素的排列顺序不会得到保证。
如果需要对列表去重并保留原有顺序,可以使用:
numbers = [3, 1, 2, 3, 2, 4] result = list(dict.fromkeys(numbers)) print(result)
执行结果:
[3, 1, 2, 4]
上述保序去重方法要求元素可以作为字典键使用,适用于 Python 3.7 及以上版本。
集合元素的类型限制
集合中的元素必须是可哈希(Hashable)的对象。
常见的可哈希对象包括整数、浮点数、字符串,以及所有成员都可哈希的元组。
my_set = {1, 3.14, "Python", (1, 2)}
print(len(my_set))
执行结果:
4
列表、字典和普通集合通常不可哈希,不能直接作为集合元素。
my_set = {[1, 2], [3, 4]}
# TypeError: unhashable type: 'list'
如果需要将一个集合作为另一个集合的元素,可以使用不可变集合 frozenset。
集合运算
Python 集合支持数学中常见的集合运算,例如并集、交集、差集和对称差集。
假设有两个集合:
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
常见运算符如下:
| 运算 | 运算符 | 方法 | 说明 |
|---|---|---|---|
| 并集 | | |
union() |
两个集合中的所有元素,去除重复项 |
| 交集 | & |
intersection() |
同时属于两个集合的元素 |
| 差集 | - |
difference() |
属于第一个集合,但不属于第二个集合的元素 |
| 对称差集 | ^ |
symmetric_difference() |
只属于其中一个集合的元素 |
实例
b = {3, 4, 5, 6}
# 并集
print("并集:", sorted(a | b))
# 交集
print("交集:", sorted(a & b))
# 差集
print("差集:", sorted(a - b))
# 对称差集
print("对称差集:", sorted(a ^ b))
执行结果:
并集: [1, 2, 3, 4, 5, 6] 交集: [3, 4] 差集: [1, 2] 对称差集: [1, 2, 5, 6]
说明:差集具有方向性,a - b 与 b - a 的结果通常不同。
除了运算符,还可以使用集合方法:
a.union(b) a.intersection(b) a.difference(b) a.symmetric_difference(b)
这些方法返回新的集合,不会直接修改原集合。
集合运算符通常要求两个操作数是集合类型;对应的方法则可以根据具体方法接受列表、元组等可迭代对象。
集合推导式
与列表推导式类似,Python 也支持集合推导式(Set Comprehension),可以使用简洁的语法创建集合。
基本语法:
{expression for item in iterable if condition}
其中,if condition 是可选条件。
实例
squares = {x * x for x in range(1, 6)}
print(sorted(squares))
# 过滤字符串中的指定字符
letters = {
x for x in "abracadabra"
if x not in "abc"
}
print(sorted(letters))
执行结果:
[1, 4, 9, 16, 25] ['d', 'r']
集合推导式也会自动去除重复元素。
集合的基本操作
1、添加元素
可以使用 add() 方法向集合添加一个元素。
语法格式:
s.add(x)
如果元素已经存在,集合不会发生变化,也不会报错。
实例
thisset.add("Facebook")
thisset.add("Google") # 已存在,不会重复添加
print(sorted(thisset))
执行结果:
['Facebook', 'Google', 'Runoob', 'Taobao']
如果需要一次添加多个元素,可以使用 update()。
语法格式:
s.update(iterable1, iterable2, ...)
update() 可以接收一个或多个可迭代对象,将其中的元素加入当前集合。
实例
# 添加列表中的元素
thisset.update([4, 5])
# 同时添加多个可迭代对象中的元素
thisset.update((6, 7), {8, 9})
print(sorted(thisset))
执行结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
注意:如果向 update() 传入字典,添加的是字典的键,而不是值。
s = {1, 2}
s.update({"a": 10, "b": 20})
print(sorted(s, key=str))
输出结果:
[1, 2, 'a', 'b']
如果想添加字典的值,可以使用 dict.values(),前提是这些值可以作为集合元素。
2、移除元素
集合提供了 remove()、discard() 和 pop() 等删除方法。
remove() 方法
remove() 用于删除指定元素。如果元素不存在,会抛出 KeyError 异常。
语法格式:
s.remove(x)
实例
thisset.remove("Taobao")
print(sorted(thisset))
# 以下操作会引发 KeyError
thisset.remove("Facebook")
执行结果:
['Google', 'Runoob'] Traceback (most recent call last): ... KeyError: 'Facebook'
discard() 方法
discard() 同样用于删除指定元素,但如果元素不存在,不会抛出异常。
语法格式:
s.discard(x)
实例
thisset.discard("Facebook") # 不存在,不报错
thisset.discard("Taobao")
print(sorted(thisset))
执行结果:
['Google', 'Runoob']
pop() 方法
pop() 用于从集合中移除并返回一个任意元素。
语法格式:
s.pop()
实例
# 移除一个元素
removed = thisset.pop()
print("移除的元素属于原集合:",
removed in {"Google", "Runoob", "Taobao", "Facebook"})
print("剩余元素个数:", len(thisset))
执行结果:
移除的元素属于原集合: True 剩余元素个数: 3
注意:pop() 并不是随机抽样函数,也不是删除集合中的第一个元素。集合没有固定顺序,因此不能预测它会返回哪个元素。
如果集合为空,调用 pop() 会抛出 KeyError 异常。
删除方法对比
| 方法 | 作用 | 元素不存在时 |
|---|---|---|
remove(x) |
删除指定元素 | 抛出 KeyError |
discard(x) |
删除指定元素 | 不报错 |
pop() |
移除并返回任意元素 | 空集合会抛出 KeyError |
3、计算集合元素个数
可以使用 len() 函数获取集合中的元素数量。
语法格式:
len(s)
实例
print(len(thisset))
thisset.add("Google")
print(len(thisset))
执行结果:
3 3
因为集合不会保存重复元素,所以再次添加 "Google" 后,元素个数不变。
4、清空集合
可以使用 clear() 方法删除集合中的所有元素。
语法格式:
s.clear()
实例
thisset.clear()
print(thisset)
print(len(thisset))
执行结果:
set() 0
这里输出的 set() 表示一个空集合。
5、判断元素是否在集合中
可以使用 in 和 not in 运算符判断元素是否属于集合。
语法格式:
x in s x not in s
实例
print("Runoob" in thisset)
print("Facebook" in thisset)
print("Facebook" not in thisset)
执行结果:
True False True
集合通常基于哈希表实现,因此成员判断在一般情况下具有较高效率,平均时间复杂度通常为 O(1),但最坏情况下可能退化。
6、判断子集、超集和不相交集合
除了并集、交集等运算,Python 还支持判断两个集合之间的包含关系。
常见方法如下:
| 方法 | 作用 |
|---|---|
issubset() |
判断当前集合是否为指定集合的子集 |
issuperset() |
判断当前集合是否包含指定集合的全部元素 |
isdisjoint() |
判断两个集合是否没有公共元素 |
实例
b = {1, 2, 3, 4}
c = {5, 6}
print(a.issubset(b))
print(b.issuperset(a))
print(a.isdisjoint(c))
# 也可以使用比较运算符
print(a <= b) # 子集
print(a < b) # 真子集
print(b >= a) # 超集
执行结果:
True True True True True True
<= 和 >= 允许两个集合相等;< 和 > 则分别表示真子集和真超集,要求两者不相等。
不可变集合 frozenset
除了普通集合 set,Python 还提供不可变集合 frozenset。
两者都具有元素不重复、无固定顺序等特点,但 frozenset 创建后不能添加或删除元素。
可以使用 frozenset() 创建不可变集合。
实例
print(sorted(a))
print(type(a))
# frozenset 支持集合运算
b = frozenset([3, 4, 5])
print(sorted(a | b))
print(sorted(a & b))
执行结果:
[1, 2, 3] <class 'frozenset'> [1, 2, 3, 4, 5] [3]
frozenset 不支持 add()、remove()、update() 等修改方法。
由于 frozenset 本身可以作为可哈希对象使用,因此也可以将它作为其他集合的元素。
nested_set = {
frozenset({1, 2}),
frozenset({3, 4})
}
print(len(nested_set))
执行结果:
2
普通的 set 不能直接作为另一个集合的元素,但 frozenset 可以。
集合使用注意事项
在使用 Python 集合时,需要注意以下几点:
- 集合没有固定顺序:不要依赖
print(set)的元素排列结果,也不要通过下标访问集合。 - 元素不能重复:重复添加相同元素不会增加集合大小。
- 元素必须可哈希:列表、字典等不可哈希对象不能直接作为集合元素。
- set() 可以接收可迭代对象:例如字符串、列表、元组;传入字典时使用的是字典的键。
- 集合可以遍历:可以通过
for循环访问元素,但遍历顺序不应作为业务依据。 - 集合不支持索引和切片:不能使用
s[0]或s[1:3]。 - 注意相等性:例如
True和1在集合中会被视为相等的元素,不能分别作为两个不同元素保存。
如果需要将集合中的元素按固定顺序显示,可以使用 sorted()。但如果集合包含无法相互比较的混合类型,直接排序可能引发 TypeError。
集合内置方法完整列表
以下整理了 Python 集合常用的内置方法。
| 方法 | 描述 |
|---|---|
| add() | 向集合添加一个元素,已存在则不做修改。 |
| clear() | 移除集合中的所有元素。 |
| copy() | 返回集合的浅拷贝。 |
| difference() | 返回差集,不修改原集合。 |
| difference_update() | 直接修改当前集合,移除同时存在于其他可迭代对象中的元素。 |
| discard() | 移除指定元素,元素不存在时不报错。 |
| intersection() | 返回交集,不修改原集合。 |
| intersection_update() | 直接修改当前集合,只保留与指定可迭代对象共有的元素。 |
| isdisjoint() | 判断两个集合是否没有公共元素。 |
| issubset() | 判断当前集合是否为指定集合的子集。 |
| issuperset() | 判断当前集合是否为指定集合的超集。 |
| pop() | 移除并返回一个任意元素,空集合会抛出 KeyError。 |
| remove() | 移除指定元素,元素不存在时抛出 KeyError。 |
| symmetric_difference() | 返回对称差集,即只存在于两个集合之一的元素。 |
| symmetric_difference_update() | 直接修改当前集合,使其只保留原集合与指定集合中非共有的元素。 |
| union() | 返回并集,不修改原集合。 |
| update() | 将一个或多个可迭代对象中的元素加入当前集合。 |
| len() | 内置函数,返回集合的元素个数。 |
注意:len() 是 Python 的内置函数,并非 set 对象自身的方法。
另外,以 _update() 结尾的集合方法通常直接修改原集合,并返回 None;而 union()、intersection() 等方法会返回新的集合。
总结
Python 集合主要用于存储不重复的数据,并支持高效的成员判断和常见集合运算。
在实际开发中,集合最常见的用途包括:
- 对列表中的重复数据进行去重。
- 判断某个元素是否存在。
- 求两个数据集合的交集、并集和差集。
- 比较两个集合之间的包含关系。
- 使用
frozenset保存不需要修改的集合。
如果需要按照索引访问数据,或者需要保留元素的插入顺序,通常应该优先考虑列表等其他数据结构;如果需要去重、集合运算或快速成员判断,则可以优先考虑集合。
