5.2.4 集合的关系和运算
数学上,集合之间有“子集”、“超集”的关系和“交、差、并”等运算,在 Python 中也提供了完成集合运算的方法,在程序中恰当使用,可以优化代码。
1. 成员与集合的关系
成员与集合只有一种关系,那就是要么属于某个集合,要么不属于。
代码语言:javascript复制>>> s = set("learn")
>>> s
{'a', 'e', 'r', 'n', 'l'}
>>> 'a' in s
True
>>> 'b' not in s
True
>>> 'b' in s
False
2. 集合与集合的关系
如果两个集合的成员完全一样,那么这两个集合则相等,否则不等——这是集合与集合之间的一种关系。
代码语言:javascript复制>>> a = set([2, 4, 6, 8])
>>> b = set([1, 3, 5, 7])
>>> a == b
False
>>> c = set([2, 4, 6, 8])
>>> a is c
False
>>> a == c
True
此外,还有一种子集(或超集)的关系,如图5-2-1所示,如果集合 A 的所有成员也是集合 B 的,那么 A 是 B 的子集,或者说 B 是 A 的超集。
图5-2-1 子集(超集)
代码语言:javascript复制>>> a
{8, 2, 4, 6}
>>> b = set([2, 4, 6, 8, 10])
>>> a.issubset(b) # a 是 b 的子集
True
>>> b.issuperset(a) # b 是 a 的超集
True
从方法命名的角度看, issubset()
和 issuperset()
表达明确,可读性强。但是,如果有读者非常习惯于数学中的运算符号 subset 、subseteq 等,会觉得这些符号更简洁明了,为此 Python 也有“同感”,所以提供了如下符号:
>>> a < b
True
>>> a <= b
True
>>> b > a
True
>>> b >= a
True
这里的 <
、<=
不应视为比较运算符,而是集合运算中的 subset 和 subseteq 符号,相应地,>
表示 supset ,>=
表示 supseteq 。
3. 集合间的运算
在数学上,集合之间有并(符号 cup )、交(符号 cap )、差(符号 - )、对称差(符号 vartriangle )等运算,在 Python 的集合对象上,也支持这些运算,且有可读性很强的方法以及对应的符号两套方式。
并
给定集合 A 、B ,定义运算 cup 为:
Acup B称为 A 和 B 的并集。
Python 中支持运算符号“ |
” 表示数学中的 cup ,也可以使用方法 union()
。
>>> a = set([1, 3, 5])
>>> b = set([3, 6, 9])
>>> a | b
{1, 3, 5, 6, 9}
>>> a.union(b)
{1, 3, 5, 6, 9}
>>> a
{1, 3, 5}
>>> b
{9, 3, 6}
从上述示例可知,集合的并运算生成了一个新的集合对象,并没有修改原有集合对象——下述各项运算均有此特点。
利用符号 |
或者方法 union()
还可以实现多个集合之间的运算。
>>> c = set([2, 4, 6])
>>> a | b | c
{1, 2, 3, 4, 5, 6, 9}
>>> a.union(b, c)
{1, 2, 3, 4, 5, 6, 9}
交
给定集合 A 、B ,定义运算 cap 为:
Acap B称为 A 和 B 的交集。
Python 中支持运算符号“ &
”表示数学中的 cap ,也可以使用方法 intersection()
。
>>> a
{1, 3, 5}
>>> b
{9, 3, 6}
>>> c
{2, 4, 6}
>>> a & b
{3}
>>> a & b & c
set()
>>> a.intersection(b)
{3}
>>> a.intersection(b, c)
set()
差
给定集合 A 、B ,定义运算 - 为:
A-B称为 B 对于 A 的差集,或相对补集。
如果有全集 U ,对于 U 的一个子集 A ,通常称 U-A 为 A 的补集。
Python 中支持运算符“ -
” 表示数学中的 - (都是键盘中的 -
键所对应的符号),也可以使用方法 difference()
。
>>> a
{1, 3, 5}
>>> b
{9, 3, 6}
>>> a - b
{1, 5}
>>> b - a # a - b 不等于 b - a
{9, 6}
>>> a.difference(b)
{1, 5}
>>> b.difference(a)
{9, 6}
对称差
给定集合 A 、B ,定义运算 vartriangle 为:
Python 中支持运算符“ ^
”表示数学中的 vartriangle ,也可以使用方法 symmetric_difference()
。
>>> a
{1, 3, 5}
>>> b
{9, 3, 6}
>>> a ^ b
{1, 5, 6, 9}
>>> a.symmetric_difference(b)
{1, 5, 6, 9}
在使用运算符进行有关集合运算时,参与运算的必须是集合——可变集合或者不可变集合。
代码语言:javascript复制>>> a
{1, 3, 5}
>>> fs = frozenset([2,3,4])
>>> a & fs # (11)
{3}
注释(11)计算了可变集合与不可变集合的交集,Python 会自动先执行 set(fs)
,将不可变集合转换为可变集合,再计算 a & set(fs)
。
但是,如果使用集合的方法 union()
、 intersection()
、 difference()
、 symmetric_difference()
、 issubset()
、 issuperset()
,它们的参数除了集合对象之外,可以是其他可迭代对象——任何可用 set()
创建集合的 Python 对象。
>>> a
{1, 3, 5}
>>> a.union([5, 6, 7])
{1, 3, 5, 6, 7}
>>> a.union({5:'a', 6:'b'})
{1, 3, 5, 6}
>>> a.union("255")
{1, 3, 5, '5', '2'}
★自学建议 从开始自学到现在,一直在学 Python 的内置对象类型,有的读者可能会质疑:这些东西怎么用?甚至有的人会认为,这样的自学方式太慢了。 现代社会生活节奏比较快,为了迎合我们的这种感觉,就有了诸如“X天学会某某”的广告满天飞——其中 X 是不能大于21的,因为有人说21天会改掉一个坏习惯并养成一个好习惯,虽然这并未得到严格证实,但很多人相信——这无疑对本来焦虑的人们雪上加霜。 不过,我们还是要理智地思考:学习能不能“快餐化”?或许有的内容可以。根据我个人经验,至少在编程语言的学习中,“快餐化”地学习,貌似在较短时间内入门,实则只是照葫芦画瓢——以所谓的实战项目自欺欺人。所以,请读者稍安勿躁,打牢基础,养成独立研习的习惯,掌握学习方法,假以时日,必能厚积薄发,前途无量。 ”