跳转到内容

Python 编程/集合

来自 Wikibooks,开放世界中的开放书籍


从 2.3 版本开始,Python 提供了数学集合的实现。最初,此实现必须从标准模块set导入,但在 Python 2.6 中,类型 set 和 frozenset 变成了内置类型。集合是对象的无序集合,与列表和元组等序列对象不同,在序列对象中,每个元素都有索引。集合不能包含重复的成员 - 给定对象在一个集合中出现 0 或 1 次。集合的所有成员都必须是可散列的,就像字典键一样。整数、浮点数、元组和字符串是可散列的;字典、列表和其他集合(除了 frozensets)不可散列。

Python 中的集合概览

set1 = set()                   # A new empty set
set1.add("cat")                # Add a single member
set1.update(["dog", "mouse"])  # Add several members, like list's extend
set1 |= set(["doe", "horse"])  # Add several members 2, like list's extend
if "cat" in set1:              # Membership test
  set1.remove("cat")
#set1.remove("elephant") - throws an error
set1.discard("elephant")       # No error thrown
print(set1)
for item in set1:              # Iteration AKA for each element
  print(item)
print("Item count:", len(set1))# Length AKA size AKA item count
#1stitem = set1[0]             # Error: no indexing for sets
isempty = len(set1) == 0       # Test for emptiness
set1 = {"cat", "dog"}          # Initialize set using braces; since Python 2.7
#set1 = {}                     # No way; this is a dict
set1 = set(["cat", "dog"])     # Initialize set from a list
set2 = set(["dog", "mouse"])
set3 = set1 & set2             # Intersection
set4 = set1 | set2             # Union
set5 = set1 - set3             # Set difference
set6 = set1 ^ set2             # Symmetric difference
issubset = set1 <= set2        # Subset test
issuperset = set1 >= set2      # Superset test
set7 = set1.copy()             # A shallow copy
set7.remove("cat")
print(set7.pop())              # Remove an arbitrary element
set8 = set1.copy()
set8.clear()                   # Clear AKA empty AKA erase
set9 = {x for x in range(10) if x % 2} # Set comprehension; since Python 2.7
print(set1, set2, set3, set4, set5, set6, set7, set8, set9, issubset, issuperset)

创建集合

[编辑 | 编辑源代码]

创建集合的一种方法是将任何顺序对象传递给“set”构造函数。

>>> set([0, 1, 2, 3])
set([0, 1, 2, 3])
>>> set("obtuse")
set(['b', 'e', 'o', 's', 'u', 't'])

我们还可以使用“add”函数逐个向集合添加元素。

>>> s = set([12, 26, 54])
>>> s.add(32)
>>> s
set([32, 26, 12, 54])

请注意,由于集合不包含重复元素,因此如果我们再次将 s 的成员之一添加到 s 中,“add”函数将不起作用。相同的行为也发生在“update”函数中,该函数将一组元素添加到集合中。

>>> s.update([26, 12, 9, 14])
>>> s
set([32, 9, 12, 14, 54, 26])

请注意,您可以将任何类型的顺序结构,甚至另一个集合,传递给 update 函数,无论用于初始化集合的结构是什么。

set 函数还提供了一个复制构造函数。但是,请记住,复制构造函数将复制集合,但不会复制各个元素。

>>> s2 = s.copy()
>>> s2
set([32, 9, 12, 14, 54, 26])

成员测试

[编辑 | 编辑源代码]

我们可以使用与顺序数据类型相同的“in”运算符检查对象是否在集合中。

>>> 32 in s
True
>>> 6 in s
False
>>> 6 not in s
True

我们还可以测试整个集合的成员资格。给定两个集合,我们检查 是否是 子集或超集。

>>> 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”函数查找集合中的元素数量。

移除元素

[编辑 | 编辑源代码]

有三个函数可以从集合中移除单个元素,分别称为 pop、remove 和 discard。第一个,pop,只是从集合中移除一个元素。请注意,对于它选择移除哪个元素没有定义的行为。

>>> s = set([1,2,3,4,5,6])
>>> s.pop()
1
>>> s
set([2,3,4,5,6])

我们还有“remove”函数来移除指定的元素。

>>> s.remove(3)
>>> s
set([2,4,5,6])

但是,移除集合中不存在的元素会导致错误。

>>> s.remove(9)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
KeyError: 9

如果您希望避免此错误,请使用“discard”。它的功能与 remove 相同,但如果元素不在集合中,则只会不做任何事情

我们还有另一个用于从集合中移除元素的操作,clear,它只是从集合中移除所有元素。

>>> s.clear()
>>> s
set([])

遍历集合

[编辑 | 编辑源代码]

我们还可以让循环遍历集合中的每个元素。但是,由于集合是无序的,因此迭代将遵循哪个顺序是未定义的。

>>> s = set("blerg")
>>> for n in s:
...     print(n, "", end="")
...
r b e l g

集合操作

[编辑 | 编辑源代码]

Python 允许我们执行所有标准的数学集合操作,使用集合的成员。请注意,每个集合操作都有几种形式。其中一种形式,s1.function(s2) 将返回另一个集合,该集合是通过将“function”应用于 创建的。另一种形式,s1.function_update(s2),将更改 为通过 的“function”创建的集合。最后,一些函数有等效的特殊运算符。例如,s1 & s2 等效于 s1.intersection(s2)

任何同时存在于 中的元素都将出现在它们的交集中。

>>> s1 = set([4, 6, 9])
>>> s2 = set([1, 6, 8])
>>> s1.intersection(s2)
set([6])
>>> s1 & s2
set([6])
>>> s1.intersection_update(s2)
>>> s1
set([6])

两个集合的并集是这两个集合的合并。任何存在于 中的元素都将出现在它们的并集中。

>>> s1 = set([4, 6, 9])
>>> s2 = set([1, 6, 8])
>>> s1.union(s2)
set([1, 4, 6, 8, 9])
>>> s1 | s2
set([1, 4, 6, 8, 9])

请注意,并集的更新函数仅仅是“update” 上面提到的。

对称差

[编辑 | 编辑源代码]

两个集合的对称差是属于其中一个集合但不属于两个集合的元素的集合(在逻辑中也称为异或)。

>>> s1 = set([4, 6, 9])
>>> s2 = set([1, 6, 8])
>>> s1.symmetric_difference(s2)
set([8, 1, 4, 9])
>>> s1 ^ s2
set([8, 1, 4, 9])
>>> s1.symmetric_difference_update(s2)
>>> s1
set([8, 1, 4, 9])

集合差

[编辑 | 编辑源代码]

Python 还可以找到 集合差,也就是属于 但不属于 的元素。

>>> s1 = set([4, 6, 9])
>>> s2 = set([1, 6, 8])
>>> s1.difference(s2)
set([9, 4])
>>> s1 - s2
set([9, 4])
>>> s1.difference_update(s2)
>>> s1
set([9, 4])

多个集合

[编辑 | 编辑源代码]

从 Python 2.6 开始,“union”、“intersection” 和“difference” 可以处理多个输入。例如,使用“set.intersection()”。

>>> s1 = set([3, 6, 7, 9])
>>> s2 = set([6, 7, 9, 10])
>>> s3 = set([7, 9, 10, 11])
>>> set.intersection(s1, s2, s3)
set([9, 7])

冻结集

[编辑 | 编辑源代码]

冻结集(frozenset)基本上与集合相同,除了它是不可变的——一旦创建,其成员就不能更改。由于它们是不可变的,因此它们也是可散列的,这意味着冻结集可以用作其他集合中的成员以及字典的键。冻结集具有与普通集合相同的函数,除了所有更改内容的函数(update、remove、pop 等)都不可用。

>>> fs = frozenset([2, 3, 4])
>>> s1 = set([fs, 4, 5, 6])
>>> s1
set([4, frozenset([2, 3, 4]), 6, 5])
>>> fs.intersection(s1)
frozenset([4])
>>> fs.add(6)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'frozenset' object has no attribute 'add'
  1. 创建一个集合 {'cat', 1, 2, 3},并将其命名为 s。
  2. 创建一个集合 {'c', 'a', 't', '1', '2', '3'}。
  3. 创建一个冻结集 {'cat', 1, 2, 3},并将其命名为 fs。
  4. 创建一个包含冻结集 fs 的集合,它应该看起来像 {frozenset({'cat', 2, 3, 1})}。
华夏公益教科书