Python3 集合

集合(set)是一个无序的不重复元素序列。可以使用大括号{}或者set()函数创建集合,注意:创建一个空集合必须使用set()而不是{},因为{}是用来创建一个空字典。

创建集合
>>> s1 = set("apple")
>>> s1
{'a', 'p', 'e', 'l'}

上面的例子中,把字符串中的字符拆解开,形成集合。特别注意,apple中有两个p,但是集合是不能有重复元素的,因此输出的结果中只有一个p。也由于此特性,集合是一种非常简单高效的元素去重方式。

>>> s2 = {'apple','banana','orange'}
>>> s2
{'apple', 'banana', 'orange'}

还可以使用集合推导式创建集合

>>> s3 = {x for x in 'abcdefgfijkedghadbc' if x not in 'abc'}
>>> s3
{'h', 'e', 'j', 'd', 'i', 'f', 'g', 'k'}

还需要注意的一点是,集合中的元素必须是不可变的。

>>> s4 = {"book",[1,2,3]}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> s4 = {"book",{"name":"Python","lang":"english"}}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
# 使用set()创建也是一样
>>> s4 = set(["book",[1,2,3]])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

从上面我们还可以知道,虽然字典的值需要是不可变的,但字典本身是可变的,因此它不能作为集合的元素。特别说明,利用set()建立起来的集合是可变集合,即它是unhashable类型的。

集合的基本操作及方法

S.add(),添加元素

>>> s = set()
>>> s.add('Python')
>>> s
{'Python'}

S.update(),用原有的集合自身和其他东西构成新的集合来更新原有的集合;且参数可以是列表、元组、字典等。

>>> s1 = {"Python","Java"}
>>> s1
{'Java', 'Python'}
>>> s2 = {"C++"}
>>> s1.update(s2)
>>> s1
{'Java', 'Python', 'C++'}
>>> s1.update("C")
>>> s1
{'C', 'Java', 'Python', 'C++'}
>>> s1.update([1,2,3])
>>> s1
{1, 2, 3, 'Java', 'C++', 'C', 'Python'}
>>> s1.update(('1','2','3'))
>>> s1
{1, 2, 3, 'Java', 'C++', 'C', 'Python', '2', '1', '3'}
# 多个参数可以用逗号隔开
>>> s1.update([4,5],[6,7])
>>> s1
{1, 2, 3, 'Java', 'C++', 4, 5, 6, 'C', 7, 'Python', '2', '1', '3'}

S.pop(),随机删除集合中的一个元素并返回该元素。

>>> s1 = {'Python','Java','C++','C'}
>>> s1.pop()
'C'
>>> s1
{'Java', 'Python', 'C++'}

S.remove(x),将元素x从集合S中移除,如果元素不存在,则会发生错误。

>>> s1 = {'Python','Java','C++','C'}
>>> 
>>> s1.remove("C++")
>>> s1
{'C', 'Java', 'Python'}
>>> s1.remove("php")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'php'

S.discard(),与remove()类似,移除集合中的指定元素,且如果元素不存在,不做任何操作,也不会报错。

>>> s1 = {'Python','Java','C++','C'}
>>> s1.discard('Java')
>>> s1
{'C', 'Python', 'C++'}
>>> s1.discard('php')
>>> s1
{'C', 'Python', 'C++'}

S.clear(),清除集合中所有的元素。

>>> s1 = {'Python','Java','C++','C'}
>>> s1.clear()
>>> s1
set()

S.copy(),拷贝一个集合。

>>> s1 = {'Python','Java','C++','C'}
>>> s2 = s1.copy()
>>> s2
{'C', 'Java', 'Python', 'C++'}

S.isdisjoint(),判断两个集合是否包含相同的元素,如果没有包含返回True,如果包含返回False

>>> x = {'apple','banana','cherry'}
>>> y = {'google','baidu','souhu'}
>>> x.isdisjoint(y)
True
>>> x = {'apple','banana','cherry'}
>>> y = {'google','baidu','apple'}
>>> x.isdisjoint(y)
False
集合的运算
元素与集合的关系

元素与集合只有一种关系,元素要么属于某个集合,要么不属于。

>>> s1 = {'Python','Java','C++','C'}
>>> 'Python' in s1
True
>>> 'php' in s1
False
集合与集合的关系

集合a是否等于集合b,即判断两个集合的元素是否完全一样。

>>> a = set('Python')
>>> a
{'h', 'n', 't', 'P', 'y', 'o'}
>>> b = set('Python')
>>> b
{'h', 'n', 't', 'P', 'y', 'o'}
>>> a == b
True
>>> a != b
False

集合a是否是集合b的子集,或者反过来说,集合b是否是集合a的超集。即a的元素也都是b的元素,但是b的元素比a的元素数量多。可以使用a<ba.issubset(b)b.issuperset(a)

>>> a = {1,2,3,4,5}
>>> b = {0,1,2,3,4,5,6,7}
>>> a < b		   # 通过 < 来判断a是否是b的子集
True
>>> a.issubset(b)	# a是否是b的子集
True
>>> b.issuperset(a)	# b是否是a的超集
True

集合a与集合b的并集。可以使用a | ba.union(b)

>>> a = set('Pyt')
>>> b = set('hon')
>>> a | b
{'h', 'n', 'P', 't', 'y', 'o'}
>>> a.union(b)
{'h', 'n', 'P', 't', 'y', 'o'}

集合a与集合b的交集,即得到ab所公有的元素。可以使用a & ba.intersection(b)

>>> a = {1,2,3,4,5}
>>> b = {0,4,5,6,7,8,9}
>>> a & b
{4, 5}
>>> a.intersection(b)
{4, 5}

还可以使用intersection_update()方法,不同于intersection()的是在原始的集合上移除不重叠的元素,即改变了原始集合

>>> a.intersection_update(b)
>>> a
{4, 5}

集合a与集合b的差集,即a相对于b不同的部分元素。可以使用a-ba.difference(b)

>>> a = set("abcdefg")
>>> b = set("abcfwmjs")
>>> a - b
{'g', 'd', 'e'}
>>> a.difference(b)
{'g', 'd', 'e'}
# 如果计算b-a,b.difference(a),则结果就会不一样,因为是b相对于a不同的部分
>>> b - a
{'w', 'm', 's', 'j'}
>>> b.difference(a)
{'w', 'm', 's', 'j'}

还可以使用difference_update(),不同于difference的是直接在原始集合上移除元素。

>>> a.difference_update(b)
>>> a
{'g', 'd', 'e'}

集合a与集合b的对称差集,返回两个集合中不重复的元素集合。实际上就是a-bb-a的并集,即可以使用上面的方法多次运算得到结果,但考虑到兼并运算,Python中提供了另一个方法:symmetric_difference()

>>> a = set("abcdefg")
>>> b = set("abcafwmjs")
>>> a.symmetric_difference(b)
{'e', 'j', 'm', 's', 'd', 'w', 'g'}

还可以使用symmetric_difference_update(),与symmetric_difference()不同的是,该方法是移除当前集合中在另外一个指定集合相同的元素,并将另外一个指定集合中不同的元素插入到当前集合中。

>>> a = set("abcdefg")
>>> b = set("abcafwmjs")
>>> a.symmetric_difference_update(b)
>>> a
{'e', 'j', 'd', 'm', 's', 'w', 'g'}

最后再来看下一个小例子:

>>> a = set(['a','b','c','r','g'])
>>> b = set(['b','r','d','h','j'])
>>> a and b
{'h', 'j', 'd', 'b', 'r'}

为什么上述例子的结果会是这样的呢?实际上我们可以看出,a and b最终返回的结果其实就是集合b。这里实际上跟集合的运算没有关系,就是两个逻辑条件之间的判断,集合a不为空,继续判断集合b,集合b也不为空,此时就以b作为结果返回。

不变的集合

上面说到用set()创建的集合是可变的,即可原地修改的,也是不可哈希的(unhashable)的集合。但是如果我们采用frozenset()就可以创建一种不能原地修改,不可变的集合。frozenset,顾名思义,是一个被冻结的集合,当然不能被修改,即这种集合是可哈希的,即就是hashable类型的集合。

>>> f_set = frozenset('Python')
>>> f_set
frozenset({'h', 'n', 't', 'P', 'y', 'o'})
>>> f_set.add("great")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'frozenset' object has no attribute 'add'

从上面的报错可以知道这种集合没有类似add的函数,自然就不能被修改。下面来看下这种不可修改的对象有哪些属性和方法:

>>> dir(f_set)
['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'copy', 'difference', 'intersection', 'isdisjoint', 'issubset', 'issuperset', 'symmetric_difference', 'union']

从结果可以看出,它没有可以改变集合的那些增删改除等操作方法,但与可修改集合一样的是有集合之间运算的方法,最重要的是它有__hash__这个方法,这也标识着它是hashable的,即不变的集合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值