当您需要删除序列中的重复项或打算执行一些数学运算时,您可以使用集合对象。集合是可散列对象的无序容器。稍后您将了解有关可散列对象的更多信息,现在请记住,只有不可变数据类型才能成为集合的元素。由于它们的形式,集合不记录元素位置或插入顺序,因此您无法通过索引检索元素。
创建集
首先,我们通过在花括号中列出其元素来创建一个集合。唯一的例外是可以在函数的帮助下形成的空集set()
:
empty_set = set()
print(type(empty_set)) # <class 'set'>
empty_dict = {}
print(type(empty_dict)) # <class 'dict'>
如果您将字符串或列表传递给set()
,该函数将返回一个包含此字符串/列表的所有元素的集合:
flowers = {'rose', 'lilac', 'daisy'}
# the order is not preserved
print(flowers) # {'daisy', 'lilac', 'rose'}
letters = set('philharmonic')
print(letters) # {'h', 'r', 'i', 'c', 'o', 'l', 'a', 'p', 'm', 'n'}
每个元素仅被视为一个集合的一部分,因此双字母被计为一个元素:
letters = set('Hello')
print(len(letters)) # the length equals 4
print(letters) # {'H', 'e', 'o', 'l'}
此外,使用集合可以帮助您避免重复:
states = ['Russia', 'USA', 'USA', 'Germany', 'Italy']
print(set(states)) # {'Russia', 'USA', 'Italy', 'Germany'}
看一下:由于命名元素的顺序没有任何作用,因此以下两组将是相等的。
set1 = {'A', 'B', 'C'}
set2 = {'B', 'C', 'A'}
print(set1 == set2) # True
使用集合的元素
- 借助
len()
函数获取集合元素的数量。 - 使用
for循环遍历所有元素
。 - 检查元素是否属于特定集合(
in / not in
运算符),您将获得布尔值。
nums = {1, 2, 2, 3}
print(1 in nums, 4 not in nums) # True True
add()
使用方法或update()
使用另一个集合将新元素添加到集合中
nums = {1, 2, 2, 3}
nums.add(5)
print(nums) # {1, 2, 3, 5}
another_nums = {6, 7}
nums.update(another_nums)
print(nums) # {1, 2, 3, 5, 6, 7}
# we can also add a list
text = ['how', 'are', 'you']
nums.update(text)
print(nums) # {'you', 1, 2, 3, 5, 6, 7, 'are', 'how'}
# or a string
word = 'hello'
nums.add(word)
print(nums) # {1, 2, 3, 'how', 5, 6, 7, 'hello', 'you', 'are'}
请注意,当我们使用列表更新集合时,这些是添加到集合中的列表元素,而不是列表本身。
discard/remove
使用方法从特定集合中删除元素。它们操作之间的唯一区别是该集合中不存在要删除的元素的情况。在这种情况下,discard
不执行任何操作并remove
生成KeyError
异常。
nums.remove(2)
print(nums) # {1, 3, 5}
empty_set = set()
empty_set.discard(2) # nothing happened
empty_set.remove(2) # KeyError: 2
- 使用方法删除一个随机元素
pop()
。由于它将是随机的,因此您无需选择参数。
nums = {1, 2, 2, 3}
nums.pop()
print(nums) # {2, 3}
-
clear()
使用方法从集合中删除所有元素。
什么时候使用集合?
集合(以及所有一般的无序集合)的一个重要特性是它们允许您运行成员资格测试比列表快得多。在现实生活中,如果您有一个列表并且您尝试手动检查其中是否存在特定项目,那么唯一的方法是查看整个列表直到找到该项目。Python 做同样的事情:它从列表的开头开始寻找所需的项目,因为它不知道它可以放在哪里。如果项目位于末尾或根本没有这样的项目,Python 将在发现这一事实时遍历列表中的大部分项目。因此,如果您的程序多次在大列表中查找项目,它会很慢。
这就是集合来帮助我们的地方!集合成员资格测试几乎立即起作用,因为它们使用不同的存储和排列值的方式。因此,根据具体情况,您需要决定什么对您更重要:保持集合中项目的顺序或以更快的方式测试成员资格。在第一种情况下,将您的项目存储在列表中是合理的,在第二种情况下,最好使用 set。
Frozenset
set
和frozenset
之间的唯一区别是 set 是可变数据类型,但 freezeset 不是。要创建一个frozenset,我们使用该frozenset()
函数。
empty_frozenset = frozenset()
print(empty_frozenset) # frozenset()
我们还可以从列表、字符串或集合中创建 freezeset:
frozenset_from_set = frozenset({1, 2, 3})
print(frozenset_from_set) # frozenset({1, 2, 3})
frozenset_from_list = frozenset(['how', 'are', 'you'])
print(frozenset_from_list) # frozenset({'you', 'are', 'how'})
如上所述,frozenset 是不可变的。这意味着虽然集合的元素可以更改,但在 freezeset 中它们在创建后保持不变。您不能添加或删除项目。
empty_frozenset.add('some_text') # AttributeError: 'frozenset' object has no attribute 'add'
那么为什么我们需要frozenset呢?由于一个集合是可变的,我们不能让它成为另一个集合的元素。
text = {'hello', 'world'}
nested_text = {'!'}
nested_text.add(text) # TypeError: unhashable type: 'set'
但是使用frozenset,就不会出现这样的问题。由于其散列性和不变性,它可以是另一个集合的元素或另一个frozenset集合的元素。
some_frozenset = frozenset(text)
nested_text.add(some_frozenset)
print(nested_text) # {'!', frozenset({'world', 'hello'})}
此外,frozensets 的这些属性允许它们成为 Python 字典中的键,但稍后您将了解更多信息。
概括
考虑到所有因素,现在您知道如何使用集合了:
- 您知道如何创建一个新集合以及可以在集合中存储什么(仅限不可变数据类型)。
- 您了解 set 和其他 Python 对象之间的区别。
- 您可以使用集合的元素:添加新元素或删除它们、区分
discard
和remove
方法等。 - 你知道什么时候使用集合(这真的可以节省你的时间!)。
- 你知道这
frozenset
是 set 的不可变替代品。