Python编程
集合(Set)
在 Python 中,集合是一个无序的对象集合,通过键而不是索引来访问元素。集合中的元素必须是可哈希的:整数、浮点数、元组和字符串是可哈希的,而列表、字典和除冻结集合外的集合则不是。
概述
Python 中集合的基本用法:
set1 = set() # 创建一个空集合
set1.add("cat") # 添加单个成员
set1.update(["dog", "mouse"]) # 添加多个成员,类似于列表的 extend
set1 |= set(["doe", "horse"]) # 再添加多个成员,类似于列表的 extend
if "cat" in set1: # 成员测试
set1.remove("cat")
# set1.remove("elephant") - 报错
set1.discard("elephant") # 不抛出错误
print(set1)
for item in set1: # 遍历集合
print(item)
print("Item count:", len(set1)) # 长度测试
# set1[0] # 报错:集合不支持索引
isempty = len(set1) == 0 # 测试是否为空
set1 = {"cat", "dog"} # 使用大括号初始化集合(Python 2.7 及以后版本)
# set1 = {} # 错误:这是一个字典
set1 = set(["cat", "dog"]) # 从列表初始化集合
set2 = set(["dog", "mouse"])
set3 = set1 & set2 # 交集
set4 = set1 | set2 # 并集
set5 = set1 - set3 # 差集
set6 = set1 ^ set2 # 对称差集
issubset = set1 <= set2 # 子集测试
issuperset = set1 >= set2 # 超集测试
set7 = set1.copy() # 浅拷贝
set7.remove("cat")
print(set7.pop()) # 移除一个任意元素
set8 = set1.copy()
set8.clear() # 清空集合
set9 = {x for x in range(10) if x % 2} # 集合推导式(Python 2.7 及以后版本)
print(set1, set2, set3, set4, set5, set6, set7, set8, set9, issubset, issuperset)
构造集合
set([0, 1, 2, 3]) # {0, 1, 2, 3}
set("obtuse") # {'b', 'e', 'o', 's', 'u', 't'}
也可以通过 add
函数逐个添加元素到集合:
s = set([12, 26, 54])
s.add(32)
print(s) # {32, 26, 12, 54}
注意,因为集合不允许重复元素,如果尝试再次添加集合中的某个成员,add
函数不会有任何效果。update
函数也是一样,它添加一组元素到集合中。
s.update([26, 12, 9, 14])
print(s) # {32, 9, 12, 14, 54, 26}
成员测试
使用 in
运算符可以检查某个对象是否在集合中:
32 in s # True
6 in s # False
6 not in s # True
还可以测试整个集合的成员资格。给定两个集合 S1
和 S2
,我们可以检查 S1
是否是 S2
的子集或超集。
s.issubset(set([32, 8, 9, 12, 14, -4, 54, 26, 19])) # True
s.issuperset(set([9, 12])) # True
注意,issubset
和 issuperset
方法也可以接受序列类型作为参数:
s.issuperset([32, 9]) # True
<=
和 >=
运算符也可以分别表示 issubset
和 issuperset
函数:
set([4, 5, 7]) <= set([4, 5, 7, 9]) # True
set([9, 12, 15]) >= set([9, 12]) # True
与列表、元组和字符串一样,可以使用 len
函数来查找集合中的项数。
移除集合中的元素
在 Python 中,有三种方法可以从集合中移除单个元素:pop
、remove
和 discard
。其中,pop
方法随机移除集合中的一个元素。注意,pop
方法没有定义元素选择的行为。
s = set([1, 2, 3, 4, 5, 6])
s.pop() # 移除一个元素
print(s) # 输出:set([2, 3, 4, 5, 6])
我们也可以使用 remove
方法来移除指定的元素:
s.remove(3) # 移除元素 3
print(s) # 输出:set([2, 4, 5, 6])
然而,如果你试图移除一个不存在于集合中的元素,remove
方法会抛出 KeyError
错误:
s.remove(9) # 报错:KeyError: 9
如果你希望避免这种错误,可以使用 discard
方法。它的功能和 remove
相同,但是如果元素不存在,它不会抛出错误。
s.discard(9) # 不抛出错误
print(s) # 输出:set([2, 4, 5, 6])
此外,我们还有一个用于移除集合中所有元素的操作 clear
:
s.clear() # 清空集合
print(s) # 输出:set([])
遍历集合
我们可以使用循环遍历集合中的每个元素。然而,由于集合是无序的,所以无法确定遍历的顺序。
s = set("blerg")
for n in s:
print(n, "", end="")
# 输出:r b e l g
集合操作
Python 允许我们执行所有标准的数学集合操作,使用集合成员。每个集合操作有两种形式:一种是 s1.function(s2)
,它会返回一个新的集合;另一种是 s1.function_update(s2)
,它会修改集合 s1
,使其成为 s1
和 s2
的“函数”结果。
交集(Intersection)
交集是两个集合的共同元素。
s1 = set([4, 6, 9])
s2 = set([1, 6, 8])
print(s1.intersection(s2)) # 输出:{6}
print(s1 & s2) # 输出:{6}
s1.intersection_update(s2)
print(s1) # 输出:{6}
并集(Union)
并集是两个集合的合并。任何在 s1
或 s2
中的元素都会出现在并集中。
s1 = set([4, 6, 9])
s2 = set([1, 6, 8])
print(s1.union(s2)) # 输出:{1, 4, 6, 8, 9}
print(s1 | s2) # 输出:{1, 4, 6, 8, 9}
对称差集(Symmetric Difference)
对称差集是两个集合中独有的元素,存在于其中一个集合中但不在两个集合中。
s1 = set([4, 6, 9])
s2 = set([1, 6, 8])
print(s1.symmetric_difference(s2)) # 输出:{8, 1, 4, 9}
print(s1 ^ s2) # 输出:{8, 1, 4, 9}
s1.symmetric_difference_update(s2)
print(s1) # 输出:{8, 1, 4, 9}
差集(Set Difference)
差集是存在于 s1
中但不在 s2
中的元素。
s1 = set([4, 6, 9])
s2 = set([1, 6, 8])
print(s1.difference(s2)) # 输出:{9, 4}
print(s1 - s2) # 输出:{9, 4}
s1.difference_update(s2)
print(s1) # 输出:{9, 4}
多个集合操作
从 Python 2.6 开始,集合的 union
、intersection
和 difference
操作可以接受多个输入集合。
s1 = set([3, 6, 7, 9])
s2 = set([6, 7, 9, 10])
s3 = set([7, 9, 10, 11])
print(set.intersection(s1, s2, s3)) # 输出:{9, 7}
冻结集合(frozenset)
冻结集合与普通集合非常相似,区别在于它是不可变的——一旦创建,元素不能被修改。由于不可变,冻结集合也是可哈希的,因此可以作为其他集合的成员或字典的键。冻结集合与普通集合有相同的函数,除了修改内容的函数(如 update
、remove
、pop
等)不可用。
fs = frozenset([2, 3, 4])
s1 = set([fs, 4, 5, 6])
print(s1) # 输出:{4, frozenset([2, 3, 4]), 6, 5}
print(fs.intersection(s1)) # 输出:frozenset([4])
fs.add(6) # 报错:AttributeError: 'frozenset' object has no attribute 'add'
练习
- 创建集合
{'cat', 1, 2, 3}
,命名为s
。 - 创建集合
{'c', 'a', 't', '1', '2', '3'}
。 - 创建冻结集合
{'cat', 1, 2, 3}
,命名为fs
。 - 创建一个包含冻结集合
fs
的集合,应该是{frozenset({'cat', 2, 3, 1})}
。