Python等你来学!!!🫣

124 阅读4分钟

在 Python 里,集合是个很有特点的容器类型。咱们先从最基本的说起,集合里的元素有两个关键特性:独一无二没有顺序。这意味着你没法像列表那样用下标(比如 s [0])访问元素,而且无论你往集合里塞多少重复的东西,它最终只会留一个。

一、创建集合的三种方式

创建集合有三种常用方法,咱们一个个看:

第一种是直接用大括号{},比如{"FishC"},这样创建的集合里就只有一个元素 "FishC"。

第二种是集合推导式,像{s for s in "FishC"}。这里会遍历字符串 "FishC" 的每个字符,最终得到的集合是{'F', 'i', 's', 'h', 'C'}(顺序不确定,因为集合无序)。

第三种是用set()函数,set("FishC")的效果和上面的集合推导式一样,也是把字符串拆成单个字符,组成集合。

不过要注意,空集合不能用{}创建(那会被当成空字典),得用set()。

二、集合的基础操作

检查元素是否存在

想知道某个元素在不在集合里,用in或not in就行。比如:

s = set("FishC")
print('i' in s)  # 输出True,因为's'里有'i'
print('x' not in s)  # 输出True'x'不在集合里

列表去重

集合的 “去重” 能力很实用。如果列表里有重复元素,转成集合再转回去,就能轻松去重:

nums = [1, 2, 2, 3, 3, 3]
unique_nums = list(set(nums))  # 结果是[1,2,3](顺序可能不同)

浅拷贝

用.copy()可以复制一个集合,修改原集合不会影响拷贝的集合:

a = {1, 2}
b = a.copy()
a.add(3)
print(b)  # 输出{1,2},不受a的影响

三、集合关系检测

是否无交集(isdisjoint)

a.isdisjoint(b)判断 a 和 b 有没有共同元素,没有的话返回 True。比如:

s1 = set("FishC")  # 包含'F','i','s','h','C'
s2 = set("Python")  # 包含'P','y','t','h','o','n'
print(s1.isdisjoint(s2))  # 输出False,因为两者都有'h'

子集与超集

a.issubset(b)检查 a 是不是 b 的子集(a 的元素都在 b 里);a.issuperset(b)检查 a 是不是 b 的超集(b 的元素都在 a 里)。比如:

a = {1, 2}
b = {1, 2, 3}
print(a.issubset(b))  # True,ab的子集
print(b.issuperset(a))  # True,ba的超集

也可以用运算符:a <= b等价于a.issubset(b),a >= b等价于a.issuperset(b)。如果是 “真子集”(a 是 b 的子集且 a≠b),用a < b;“真超集” 用a > b。

四、集合运算

并集、交集、差集、对称差集

  • 并集(合并所有元素):a.union(b)或a | b
  • 交集(共同元素):a.intersection(b)或a & b
  • 差集(a 有而 b 没有的元素):a.difference(b)或a - b
  • 对称差集(a 和 b 独有的元素,排除共同的):a.symmetric_difference(b)或a ^ b

注意:方法的参数可以是任何可迭代对象(比如列表、字符串),但运算符两边必须都是集合。比如:

a = {1, 2, 3}
b = {3, 4, 5}
# 方法示例(参数用列表也可以)
print(a.union([4,5,6]))  # {1,2,3,4,5,6}
# 运算符示例(必须是集合)
print(a | b)  # {1,2,3,4,5}

五、不可变集合(frozenset)

普通集合是可变的(能增删元素),但frozenset(a)会创建一个不可变集合,不能修改,所以能嵌套到其他集合里。比如:

fs = frozenset({1, 2})
s = {fs, 3}  # 合法,frozenset可以嵌套
# 下面的代码会报错,因为普通集合不能嵌套
# s = {{1,2}, 3}  # 报错:unhashable type: 'set'

六、修改集合的方法

增加元素

  • s.update(*others):把可迭代对象的每个元素添加进去。比如s.update("ab")会加 'a' 和 'b'。
  • s.add(x):把 x 整个作为元素添加。比如s.add("ab")会加字符串 "ab"。

删除元素

  • s.remove(x):删除 x,若 x 不存在则报错。
  • s.discard(x):删除 x,x 不存在也不报错(静默处理)。
  • s.pop():随机弹出一个元素(因为集合无序)。
  • s.clear():清空集合。

示例:

s = {1, 2}
s.update([3, 4])  # s变成{1,2,3,4}
s.add(5)  # s变成{1,2,3,4,5}
s.remove(3)  # s变成{1,2,4,5}
s.discard(10)  # 啥也不做,不报错
print(s.pop())  # 随机输出一个元素,比如1
s.clear()  # s变成空集合

七、哈希与集合元素的要求

集合的元素必须是 “可哈希” 的。简单说,不可变对象(如整数、字符串、元组)是可哈希的可变对象(如列表、集合)是不可哈希的。因为集合用 “散列表” 存储,靠哈希值快速查找,所以只有可哈希的才能当元素。

比如,列表不能当集合元素,但元组可以:

# 下面的代码会报错
# s = {[1,2], 3}  # 报错:unhashable type: 'list'
# 正确写法
s = {(1,2), 3}  # 合法,元组可哈希

八、为什么列表转集合效率高?

列表查找元素时,得一个个遍历,效率低;而集合用 “散列表” 存储,通过哈希值直接定位元素位置,虽然占的空间多,但查找、添加、删除的速度快很多,这就是 “以空间换时间”。所以处理大量数据去重或判断存在性时,用集合比列表更高效。