一、简述
集合其实和字典一样都是典型的以空间换时间的类型,在python中的集合通常是指set以及frozenset,由于set类型是不可散列的,frozenset是可散列的,因此可以创建一个包含不同frozen的set对象。
集合最多的是用来一组对象的去重
>>> l = ['spam', 'spam', 'eggs', 'spam']
>>> set(l)
{'eggs', 'spam'}
>>> list(set(l))
['eggs', 'spam']
集合还实现了很多基础的中缀运算符。给定两个集合a 和 b,a | b 返回的是它们的合集,a & b 得到的是交集,而 a - b得到的是差集。合理地利用这些操作,不仅能够让代码的行数变少,还能减少 Python 程序的运行时间。这样做同时也是为了让代码更易读,从而更容易判断程序的正确性,因为利用这些运算符可以省去不必要的循环和逻辑操作。
二、陷阱
my_set = {}
type(my_set)
像这样会输出什么,dict
,这是为什么?如果要创建一个空集,你必须用不带任何参数的构造方法 set()。如果只是写成 {} 的形式,跟以前一样,你创建的其实是个空字典。下面例子会帮助记忆
>>>s = {1}
>>>type(s)
<class 'set'>
>>>s
{1}
>>>s.pop()
1
>>>s
set() # 返回的是一个set()
三、构造集合
1、普通方法
myset= {1, 2, 3}
yourset = set([1, 2, 3])
倾向于前者,而不用后者,后者速度会慢一些,因为 Python 必须先从 set 这个名字来查询构造方法,然后新建一个列表,最后再把这个列表传入到构造方法里。
2、集合推导式
>>> from unicodedata import name # 从 unicodedata 模块里导入 name 函数,用以获取字符的名字。
>>> {chr(i) for i in range(32, 256) if 'SIGN' in name(chr(i),'')} # 把编码在 32~255 之间的字符的名字里有“SIGN”单词的挑出来,放到一个集合里。
{'§', '=', '¢', '#', '¤', '<', '¥', 'μ', '×', '$', '¶', '£', '©','°', '+', '÷', '±', '>', '¬', '®', '%'}
3、常用的数学运算
运算符 | 方法 | 作用 |
---|---|---|
s & z | s.__and__(z) | s 和 z 的交集 |
s &= z | s.__iand__(z) | 把 s 更新为 s 和 z 的交集 |
s | z | s.__or__(z) | s 和 z 的并集 |
z | s | s.union(it, ...) | 把可迭代的 it 和其他所有参数转化为集合,然后求它们和 s的并集 |
s |= z | s.__ior__(z) | 把 s 更新为 s 和 z 的并集 |
s - z | s.__sub__(z) | s 和 z 的差集,或者叫作相对补集 |
s -= z | s.__isub__(z) | 把 s 更新为它与 z 的差集 |
s.isdisjoint(z) | 查看 s 和 z 是否不相交(没有共同元素) | |
e in s | s.__contains__(e) | 元素 e 是否属于 s |
s <= z | s.__le__(z) | s 是否为 z 的子集 |
s < z | s.__lt__(z) | s 是否为 z 的真子集 |
s >= z | s.__ge__(z) | s 是否为 z 的父集 |
s > z | s.__gt__(z) | s 是否为 z 的真父集 |
4、 常用的一些方法
方法 | 作用 |
---|---|
s.add(e) | 把元素 e 添加到 s 中 |
s.clear() | 移除掉 s 中的所有元素 |
s.copy() | 对 s 浅复制 |
s.discard(e) | 如果 s 里有 e 这个元素的话,把它移除 |
s.pop() | 从 s 中移除一个元素并返回它的值,若 s 为空,则抛出 KeyError 异常 |
s.remove(e) | 从 s 中移除 e 元素,若 e 元素不存在,则抛出KeyError 异常 |
四、set的背后
集合和字典背后都是散列表支持,字典在python中如何存储,以及为什么set中的元素会发生乱序的现象
请参考上一篇中的小结字典背后