集合类型
- 7.1 概念
- 7.2 集合操作符和关系符号
- 7.2.1 创建集合类型和给集合赋值
- 7.2.2 访问集合中的值
- 7.2.3 更新集合
- 7.2.4 删除集合中的成员和集合
- 7.3 集合类型操作符
- 7.3.1 标准类型操作符(所有的集合类型)
- 7.3.2 集合类型操作符(所有的集合类型)
- 7.3.3 混合集合类型操作
- 7.3.4 集合类型操作符(仅适用于可变集合)
- 7.4 集合类型工厂函数
- 7.4.1 set() and frozenset()
- 7.4.2 集合类型内建方法
- 7.4.3 操作符和内建方法比较
- 7.4.4 可变集合类型的方法
- 7.4.5 集合类型操作符、函数和方法
集合能够自动去重
7.1 概念
数学上, 把 set 称做由不同的元素组成的集合,集合(set)的成员通常被称做集合元素(setelements)。Python 把这个概念引入到它的集合类型对象里。集合对象是一组无序排列的可哈希的值。
集合成员可以做字典中的键。和其他容器类型一样,集合支持用 in 和 not in 操作符检查成员, 由 len() 内建函数得到集合的基数(大小), 用 for 循环迭代集合的成员。但是因为集合本身是无序的,你不可以为集合创建索引或执行切片(slice)操作,也没有键(keys)可用来获取集合中元素的值。
集合(sets)有两种不同的类型,可变集合(set) 和 不可变集合(frozenset)。如你所想,对可变集合(set),你可以添加和删除元素,对 不可变集合(frozenset)则不允许这样做。请注意,可变集合(set)不是可哈希的,因此既不能用做字典的键也不能做其他集合中的元素。不可变集合(frozenset)则正好相反,即,他们有哈希值,能被用做字典的键或是作为集合中的一个成员。
7.2 集合操作符和关系符号
7.2.1 创建集合类型和给集合赋值
集合被创建的唯一方法 - 用集合的工厂方法 set()和 frozenset()
>>> s = set('cheeseshop')
>>> s
set(['c', 'e', 'h', 'o', 'p', 's'])
>>> t = frozenset('bookshop')
>>> t
frozenset(['b', 'h', 'k', 'o', 'p', 's'])
>>> type(s)
<type 'set'>
>>> type(t)
<type 'frozenset'>
7.2.2 访问集合中的值
可以遍历查看集合成员或检查某项元素是否是一个集合中的成员:
>>> for i in s:
...
print i
...
c
e
h
7.2.3 更新集合
各种集合内建的方法和操作符添加和删除集合的成员
>>> s.add('z')
>>> s
set(['c', 'e', 'h', 'o', 'p', 's', 'z'])
>>> s.update('pypi')
>>> s
set(['c', 'e', 'i', 'h', 'o', 'p', 's', 'y', 'z'])
>>> s.remove('z')
>>> s
set(['c', 'e', 'i', 'h', 'o', 'p', 's', 'y'])
>>> s -= set('pypi')
>>> s
set(['c', 'e', 'h', 'o', 's'])
只有可变集合能被修改。试图修改不可变集合会引发异常。
>>> t.add('z')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'frozenset' object has no attribute 'add'
7.2.4 删除集合中的成员和集合
>>> s.remove('z')
>>> del s
7.3 集合类型操作符
7.3.1 标准类型操作符(所有的集合类型)
成员关系 (in, not in)
就序列而言,Python 中的 in 和 not in 操作符决定某个元素是否是一个集合中的成员。
集合等价/不等价
等价/不等价被用于在相同或不同的集合之间做比较。两个集合相等是指,对每个集合而言,当且仅当其中一个集合中的每个成员同时也是另一个集合中的成员。集合等价/不等价与集合的类型或集合成员的顺序无关,只与集合的元素有关。
子集/超集
Sets 用 Python 的比较操作符检查某集合是否是其他集合的超集或子集。
“小于”符号(<,<==)用来判断子集
“大于”符号( >, >= )用来判断超集
“小于” 和 “大于”意味着两个集合在比较时不能相等。等于号允许非严格定义的子集和超集。
7.3.2 集合类型操作符(所有的集合类型)
联合( | )
联合(union)操作和集合的 OR(又称可兼析取(inclusive disjunction))其实是等价的,两个集合的联合是一个新集合,该集合中的每个元素都至少是其中一个集合的成员,即,属于两个集合其中之一的成员。联合符号有一个等价的方法,union().
交集( & )
你可以把交集操作比做集合的 AND(或合取)操作。两个集合的交集是一个新集合,该集合中的每个元素同时是两个集合中的成员,即,属于两个集合的成员。交集符号有一个等价的方法,intersection().
差补/相对补集( – )
两个集合(s 和 t)的差补或相对补集是指一个集合 C,该集合中的元素,只属于集合 s,而不属于集合 t。差符号有一个等价的方法,difference().
对称差分( ^ )
和其他的布尔集合操作相似,对称差分是集合的 XOR(又称”异或“ (exclusive disjunction)).两个集合(s 和 t)的对称差分是指另外一个集合 C,该集合中的元素,只能是属于集合 s 或者集合 t的成员,不能同时属于两个集合。对称差分有一个等价的方法,symmetric_difference().
>>> s=set('abcde')
>>> t=frozenset('fghijk')
>>> n=s|t
>>> n
set(['a', 'c', 'b', 'e', 'd', 'g', 'f', 'i', 'h', 'k', 'j'])
>>> s<=t
False
>>> s>t
False
>>> s<t
False
>>> s.add('fgh')
>>> s
set(['a', 'c', 'b', 'e', 'd', 'fgh'])
>>> s.add('f')
>>> print s&t
set(['f'])
>>> s-t
set(['a', 'c', 'b', 'e', 'd', 'fgh'])
>>> s^t
set(['fgh', 'a', 'c', 'b', 'e', 'd', 'g', 'i', 'h', 'k', 'j'])
7.3.3 混合集合类型操作
上面的示例中,左边的 s 是可变集合,而右边的 t 是一个不可变集合. 注意上面使用集合操作运算符所产生的仍然是可变集合,但是如果左右操作数的顺序反过来,结果就不一样了:
>>> t|s
frozenset(['a', 'c', 'b', 'e', 'd', 'g', 'f', 'i', 'h', 'k', 'j', 'fgh'])
>>> t^s
frozenset(['fgh', 'a', 'c', 'b', 'e', 'd', 'g', 'i', 'h', 'k', 'j'])
>>> t-s
frozenset(['i', 'h', 'k', 'j', 'g'])
如果左右两个操作数的类型相同,既都是可变集合或不可变集合, 则所产生的结果类型是相同的,
如果左右两个操作数的类型不相同(左操作数是 set,右操作数是 frozenset,或相反情况),则所产生的结果类型与左操作数的类型相同,上例中可以证明这一点。还要注意,加号不是集合类型的运算符
7.3.4 集合类型操作符(仅适用于可变集合)
(Union) Update ( |= )
这个更新方法从已存在的集合中添加(可能多个)成员,此方法和 update()等价.
>>> s = set('cheeseshop')
>>> u = frozenset(s)
>>> s |= set('pypi')
>>> s
set(['c', 'e', 'i', 'h', 'o', 'p', 's', 'y'])
保留/交集更新( &= )
保留(或交集更新)操作保留与其他集合的共有成员。此方法和 intersection_update()等价.
>>> s = set(u)
>>> s &= set('shop')
>>> s
set(['h', 's', 'o', 'p'])
差更新 ( –= )
对集合 s 和 t 进行差更新操作 s-=t,差更新操作会返回一个集合,该集合中的成员是集合 s 去除掉集合 t 中元素后剩余的元素。此方法和 difference_update()等价.
>>> s = set(u)
>>> s -= set('shop')
>>> s
set(['c', 'e'])
7.4 集合类型工厂函数
7.4.1 set() and frozenset()
set()和 frozenset()工厂函数分别用来生成可变和不可变的集合。如果不提供任何参数,默认会生成空集合。如果提供一个参数,则该参数必须是可迭代的,即,一个序列,或迭代器,或支持迭代的一个对象,例如:一个文件或一个字典。
7.4.2 集合类型内建方法
方法(所有的集合方法)
方法名称 | 操作 |
s.issubset(t) | 如果 s 是 t 的子集,则返回 True,否则返回 False |
s.issuperset(t) | 如果 t 是 s 的超集,则返回 True,否则返回 False |
s.union(t) | 返回一个新集合,该集合是 s 和 t 的并集 |
s.intersection(t) | 返回一个新集合,该集合是 s 和 t 的交集 |
s.difference(t) | 返回一个新集合,该集合是 s 的成员,但不是 t 的成员 |
s.symmetric_difference(t) | 返回一个新集合,该集合是 s 或 t 的成员,但不是 s 和 t 共有的成员 |
s.copy() | 返回一个新集合,它是集合 s 的浅复制 |
方法(仅适用于可变集合)add(), remove(), discard(), pop(), clear()
7.4.3 操作符和内建方法比较
很多内建的方法几乎和操作符等价。我们说"几乎等价",意思是它们间是有一个重要区别: 当用操作符时,操作符两边的操作数必须是集合。 在使用内建方法时,对象也可以是迭代类型的。为什么要用这种方式来实现呢?Python的文档里写明:
采用易懂的set(‘abc’).intersection(‘cbs’) 可以避免用 set(‘abc’) [and] ‘cbs’ 这样容易出错的构建方法。
7.4.4 可变集合类型的方法
方法名 | 操作 |
s.update(t) | 用 t 中的元素修改 s, 即,s 现在包含 s 或 t 的成员 |
s.intersection_update(t) s | 中的成员是共同属于 s 和 t 的元素。 |
s.difference_update(t) | s 中的成员是属于 s 但不包含在 t 中的元素 |
s.symmetric_difference_update(t) | s 中的成员更新为那些包含在 s 或 t 中,但不是s和 t 共有的元素 |
s.add(obj) | 在集合 s 中添加对象 obj |
s.remove(obj) | 从集合 s 中删除对象 obj;如果 obj 不是集合 s 中的元素(obj notin s),将引发 KeyError 错误 |
s.discard(obj) | 如果 obj 是集合 s 中的元素,从集合 s 中删除对象 obj; |
s.pop() | 删除集合 s 中的任意一个对象,并返回它 |
s.clear() | 删除集合 s 中的所有元素 |
7.4.5 集合类型操作符、函数和方法
所有集合类型
函数/方法名 | 等价运算符 | 说明 |
len(s) | 集合基数: 集合 s 中元素的个数 | |
set([obj]) | 可变集合工厂函数; obj 必须是支持迭代的,由 obj 中的元素创建集合,否则创建一个空集合 | |
frozenset([obj]) | 不可变集合工厂函数; 执行方式和 set()方法相同,但它返回的是不可变集合 | |
obj in s | 成员测试:obj 是 s 中的一个元素吗? | |
obj not in s | 非成员测试:obj 不是 s 中的一个元素吗? | |
s == t | 等价测试: 测试 s 和 t 是否具有相同的元素? | |
s != t | 不等价测试: 与==相反 | |
s < t | (严格意义上)子集测试; s != t 而且 s 中所有的元素都是 t 的成员 | |
s.issubset(t) | s <= t | 子集测试(允许不严格意义上的子集): s 中所有的元素都是 t 的成员 |
s > t | (严格意义上)超集测试: s != t 而且 t 中所有的元素都是 s 的成员 | |
s.issuperset(t) | s >= t | |
s.union(t) | s | t | 合并操作:s 或 t 中的元素 |
s.intersec- tion(t) | s & t | 交集操作:s 和 t 中的元素 |
s.difference(t) | s - t | 差分操作: s 中的元素,而不是 t 中的元素 |
s.symmetric_difference(t) | s ^ t | 对称差分操作:s 或 t 中的元素,但不是 s 和 t 共有的元素 |
s.copy() | 复制操作:返回 s 的(浅复制)副本 |
仅用于可变集合
函数/方法名字 | 操作符 | 等价描述 |
s.update(t) | s |= t | (Union) 修改操作: 将 t 中的成员添加 s |
s.intersection_update(t) | s &= t | 交集修改操作: s 中仅包括 s 和 t 中共有的成员 |
s.difference_update(t) | s -= t | 差修改操作: s 中包括仅属于 s 但不属于 t 的成员 |
s.symmetric_difference_update(t) | s ^= t | 对称差分修改操作: s 中包括仅属于 s 或仅属于 t 的成员 |
s.add(obj) | 加操作: 将 obj 添加到 s | |
s.remove(obj) | 删除操作: 将 obj 从 s 中删除;如果 s 中不存在obj,将引发 KeyError | |
s.discard(obj) | 丢弃操作: remove() 的友好版本-如果s中存在obj,从s中删除它 | |
s.pop() | Pop 操作: 移除并返回 s 中的任意一个元素 | |
s.clear() | 清除操作: 移除 s 中的所有元素 |