skip to content
Logo Lostman_Wang的小站

Python数据类型-基础数据类型-集合类型 --- set

  • set 对象是由具有唯一性的hashable 对象所组成的无序多项集。常见的用途包括成员检测、从序列中去除重复项以及数学中的集合类计算,例如交集、并集、差集与对称差集等等。
  • 与其他多项集一样,集合也支持 x in set, len(set) 和 for x in set。作为一种无序的多项集,集合并不记录元素位置或插入顺序。相应地,集合不支持索引、切片或其他序列类的操作。

一、构造方法

1、字面量直接构造

s1 = {1, 2, 3} # 花括号 + 逗号分隔;空集合不能用 {},那是 dict
特点说明
语法最简洁,但 不能用于空集{} 是空字典)。
元素自动去重{1, 1, 2}{1, 2}

2、内置构造函数 set(iterable=[])

s2 = set() # 空集合
s3 = set([1, 2, 3, 2]) # 任意可迭代对象 → 去重
s4 = set('hello') # {'h', 'e', 'l', 'o'}
s5 = set(range(5)) # {0, 1, 2, 3, 4}
形参默认值说明
iterable[]任何遵循迭代协议的对象(列表、元组、字符串、生成器等)。
返回值新的 set 实例O(n) 复杂度,n = 去重后元素个数。

3、集合推导式(Set Comprehension)

s6 = {x**2 for x in range(5) if x % 2 == 0} # {0, 4, 16}
  • 语法与列表/字典推导式一致,自带去重。
  • 执行过程:先构造临时列表 → 再转成集合(复杂度 O(n))。

4、从映射对象构造(键集合)

d = {'a': 1, 'b': 2}
s7 = set(d) # {'a', 'b'} —— 取字典的 key 视图
  • 等价于 set(d.keys()),同样 O(n)。

5、利用 frozenset 再转 set

fs = frozenset([1, 2, 3])
s8 = set(fs) # 把不可变集合变成可变集合
  • 当已有 frozenset 且需要可变性时,可节省一次去重。

6、性能与常见误区

6.1、空集合

  • 错误:empty = {} → 这是空字典!
  • 正确:empty = set() 或 set().

6.2、元素必须可哈希

  • 不可哈希对象(如列表、字典本身)无法加入集合
  • set([[1, 2]]) → TypeError: unhashable type: ‘list’.

6.3、大列表去重最快方式

  • unique = list(set(big_list))
  • 时间复杂度:O(n),空间额外 O(n)。

6.4、构造器 vs 字面量

  • 字面量 {1, 2, 3} 在字节码层面直接生成 BUILD_SET,
  • 比 set([1, 2, 3]) 少一次列表临时对象,略快。

二、常见方法

1、set.add(elem) -> None

1.1、作用:
  • 向集合 原地(in-place) 插入单个元素;若元素已存在则什么也不做,保证集合唯一性。
1.2、参数:
  • elem (必需)。
  • 任意 可哈希(hashable) 对象:int、str、tuple 等;
  • 不可哈希对象(list、dict、set)会抛出 TypeError: unhashable type: 'xxx'
1.3、返回值:
  • 始终返回 None(因为 set 本身被修改)。
s = {1, 2}
s.add(3) # s == {1, 2, 3}
s.add(2) # 已存在,无变化
# s.add([4, 5]) # TypeError: unhashable type: 'list'

2、set.discard(elem) -> None

2.1、作用:
  • 从集合 就地(in-place) 删除指定元素;如果元素不存在,静默忽略(不抛异常),保证集合唯一性不变。
2.2、参数:
  • elem(必需)
  • 必须是 可哈希(hashable) 对象。
  • 只要 elem == existing_item 则认为匹配,不要求对象身份一致。
2.3、返回值:
  • 始终返回 None;集合本身被修改。
s = {1, 2, 3}
s.discard(2) # s == {1, 3}
s.discard(99) # 无异常,s 仍为 {1, 3}

3、set.remove(elem) -> None

3.1、作用:
  • 从集合 就地(in-place) 删除 指定元素;若元素不存在,抛出 KeyError
3.2、参数:
  • elem (必需)。
  • 任意 可哈希 对象,必须与集合内某个元素 相等(==) 才能匹配。
  • 元素不存在时,抛出 KeyError: elem
3.3、返回值:
  • 始终返回 None(集合本身被修改)。
3.4、与相关方法对比
方法元素不存在时行为返回值
remove(elem)抛出 KeyErrorNone
discard(elem)静默忽略None
s = {1, 2, 3}
s.remove(2) # s == {1, 3}
# s.remove(4) # KeyError: 4

4、set.pop() -> element

4.1、作用:
  • 就地 从集合中 移除并返回任意一个元素
  • 由于 set 无序,具体返回哪一个元素由内部哈希表实现决定,但保证 O(1) 时间复杂度。
4.2、参数:
  • 无参数。调用时括号内 不允许传值
4.3、返回值:
  • 返回被移除的那个元素;若集合 为空,抛出 KeyError: 'pop from an empty set'
4.4、与列表 pop() 区别
方法是否可指定索引是否有序空时行为
list.pop(i=-1)✅ 可指定✅ 有序IndexError
set.pop()❌ 不可指定❌ 无序KeyError
s = {3, 1, 4}
x = s.pop() # x 可能是 1、3 或 4
print(s) # 剩余 2 个元素
s.pop() # 再弹一个
s.pop() # 再弹一个
# s.pop() # KeyError: 'pop from an empty set'

5、set.clear() -> None

5.1、作用:
  • 就地(in-place) 移除集合中的所有元素,使其变为空集合 set(),但 对象身份不变(内存地址不变)。
5.2、参数:
  • 无参数,调用时括号内 不得传入任何值
5.3、返回值:
  • 始终返回 None;集合本身被清空。
5.4、复杂度:
  • 时间复杂度 O(n),其中 n 为集合当前元素数(需逐个置空桶位)。
  • 空间复杂度 O(1),不会释放哈希表数组,仅标记空槽。
s = {1, 2, 3}
old_id = id(s)
s.clear()
print(s) # set()
print(id(s)) # 与 old_id 相同

6、set.difference(*others) -> new_set

6.1、作用:
  • 返回一个新的 set,内容是当前集合与 一个或多个 其他集合/可迭代对象的 差集;原集合保持不变。
6.2、参数:
  • *others(任意位置参数)
  • 可以是 0 个或多个 可迭代对象(set、list、tuple、dict 的键视图等)。
  • 仅当元素 可哈希 时才会参与差集运算;不可哈希元素会被忽略。
6.3、返回值:
  • 始终返回一个 全新的 set 实例,包含只在当前集合中、而不在任何 others 中的元素。
6.4、与运算符 - 的关系:
形式区别
a.difference(b, c)支持任意可迭代对象,可读性好
a - b - c只能接受 set,语法简洁
a = {1, 2, 3, 4}
b = {3, 4, 5}
# 单参数
diff = a.difference(b) # {1, 2}
# 多参数
diff2 = a.difference(b, {2, 3}) # {1}
# 原集合不变
print(a) # {1, 2, 3, 4}
>>> {1, 2, 3, 4} - {3, 4, 5, 6}
{1, 2}

7、set.union(*others) -> new_set

7.1、作用:
  • 返回一个新的 set,内容 = 当前集合 并集(所有给定集合/可迭代对象的元素去重合并);原集合不变
7.2、参数:
  • *others(任意位置参数)
  • 可以是 0 个或多个 可迭代对象(set、list、tuple、dict 的键视图等)。
  • 只使用其中 可哈希且唯一 的元素。
7.3、返回值:
  • 始终返回一个 全新的 set 实例,包含所有参与对象的并集元素。
7.4、与运算符 | 的关系:
形式区别可读性
a.union(b, c)支持任意可迭代对象可读性好
abc只能接受 set语法更简洁
a = {1, 2}
b = {2, 3}
c = [3, 4]
# 单参数
u1 = a.union(b) # {1, 2, 3}
# 多参数
u2 = a.union(b, c) # {1, 2, 3, 4}
# 原集合不变
print(a) # {1, 2}
>>> {1, 2} | {3, 4}
{1, 2, 3, 4}
>>> {1, 2} | {3, 4} | {5, 6}
{1, 2, 3, 4, 5, 6}

8、set.intersection(*others) -> new_set

8.1、作用:
  • 返回一个新的 set,内容是当前集合与 一个或多个 其他集合/可迭代对象的 交集(即所有集合共有的元素);原集合保持不变。
8.2、参数:
  • *others(任意位置参数)
  • 接受 0 个或多个 可迭代对象(可以是 setlisttupledict.keys() 等)。
  • 不要求 参数类型必须是 set;只要元素 可哈希 即可参与运算。
8.3、返回值:
  • 始终返回一个 全新的 set 实例,包含所有输入集合共有的元素
  • *others 为空,则返回 当前集合的浅拷贝(等同于 set.copy())。
8.4、与运算符 & 的区别:
形式支持类型可读性
a.intersection(b, c)任意可迭代对象
a & b & c仅限于 set简洁
a = {1, 2, 3, 4}
b = {3, 4, 5}
c = [4, 3, 6]
# 两个集合
i1 = a.intersection(b) # {3, 4}
# 多个可迭代对象
i2 = a.intersection(b, c) # {3, 4}
# 无参数 → 返回自身拷贝
i3 = a.intersection() # {1, 2, 3, 4}
# 原集合不变
print(a) # {1, 2, 3, 4}
>>> {1, 2, 3} & {3, 4, 5}
{3}

9、set.issubset(other) -> bool

9.1、作用:
  • 判断 当前集合是否为给定集合(或可迭代对象)的子集;即当前集合的所有元素都出现在对方集合中。
9.2、参数:
  • other(必需)
  • 可以是任意 可迭代对象setlisttupledict.keys() 等)。
  • 内部会先将 other 转换成临时的 set,再进行子集判断。
9.3、返回值:
  • True:当前集合 对方的子集(含 等于 的情况)。
  • False:当前集合 不是 对方的子集。
9.4、与运算符 <= 的区别
形式支持类型行为
a.issubset(b)任意可迭代对象可读性好
a <= b必须是 set语法简洁
a = {1, 2}
b = {1, 2, 3}
a.issubset(b) # True
a.issubset([1, 2, 3]) # True
b.issubset(a) # False

10、set.issuperset(other) -> bool

10.1、作用:
  • 判断当前集合是否包含给定集合(或可迭代对象)的所有元素,即当前集合是否为对方的 超集
10.2、参数:
  • other(必需)
  • 可以是任意 可迭代对象setlisttupledict.keys() 等)。
  • 内部先把 other 转成临时 set,再进行判断。
10.3、返回值:
  • True:当前集合是对方的超集(含 等于 情况)。
  • False:当前集合不是对方的超集。
10.4、与运算符 >= 的区别
形式支持类型可读性
a.issuperset(b)任意可迭代对象
a >= b必须为 set简洁
a = {1, 2, 3, 4}
b = {1, 2}
a.issuperset(b) # True
a.issuperset([1, 2]) # True
b.issuperset(a) # False

三、常见函数

1、len(set) 

  • 获取集合的长度

2、max(set)

  • 获取集合中最大的元素

3、min(set) 

  • 获取集合中最小的元素