一、基础复习
二、集合中元素的基本操作
1.可变集合set() 和不可变集合frozenset()
集合分为可变集合set()和不可变集合frozenset()
frozenset()对象是不可变的
使用update(*others)来更新集合,当显示others时,则表示支持多个对象更新
>>> t=frozenset("FishC") #不可变集合
>>> t
frozenset({'s', 'F', 'C', 'i', 'h'})
>>>
>>> s=set("FishC") #可变集合
>>> s
{'s', 'F', 'C', 'i', 'h'}
>>> s.update([1,1],"23") #集合中元素唯一,所以列表[1,1]只会添加一个元素,字符串“23”进行迭代2和3分别添加
>>> s # set()集合发生改变
{1, 's', 'F', 'C', '3', 'i', 'h', '2'}
>>> t
frozenset({'s', 'F', 'C', 'i', 'h'})
>>> t.update([1,1],"23") #frozenset()集合不会发生改变
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
t.update([1,1],"23")
AttributeError: 'frozenset' object has no attribute 'update'
2.交、差、并、对称差集更新集合的方式
更新集合的方式
s.intersection_update(*others)
s.difference_update(*others)
s.symmetric_difference_update(others)
s.update() 并集直接是update()
difference(*others)和difference_update(*others)
>>> s
{'s', 'F', 'C', 'i', 'h'}
>>> s.intersection_update("FishC") #交集
>>> s
{'s', 'F', 'C', 'i', 'h'}
>>> s.difference_update("Php","Python") #差集
>>> s
{'s', 'F', 'C', 'i'}
>>> s.symmetric_difference_update("Python") #对称差集
>>> s
{'o', 'y', 's', 'F', 'n', 'C', 't', 'P', 'i', 'h'}
>>>
3.集合中添加数据
使用add()添加字符串"45"时,将其当做一个整体添加。
使用update()方法添加字符串"45"时,会对“45”进行迭代,将4和5添加。
>>> s
{'o', 'y', 's', 'F', 'n', 'C', 't', 'P', 'i', 'h'}
>>> s.add("45")
>>> s
{'o', 'y', 's', 'F', 'n', '45', 'C', 't', 'P', 'i', 'h'}
4.删除集合中的元素
s.remove() #删除集合中没有的元素时,会报错
s.discard() #删除集合中没有的元素时,静默处理
s.pop() # 随机弹出一个元素,因为是随机存取的,所以弹出也是随机的。
clear()
s.clear() 清空集合的内容
>>> s
{'o', 'y', 's', 'F', 'n', '45', 'C', 't', 'P', 'i', 'h'}
>>> s.remove("你好") #删除集合中没有的元素时,会报错
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
s.remove("你好")
KeyError: '你好'
>>> s.discard("你好") #删除集合中没有的元素时,静默
>>> s
{'o', 'y', 's', 'F', 'n', '45', 'C', 't', 'P', 'i', 'h'}
>>> s.pop() #随机弹出一个元素,因为是随机存取的,所以弹出也是随机的。
'o'
>>> s.pop()
'y'
>>> s.pop()
's'
>>> s.pop()
'F'
>>>
>>> s
{'n', '45', 'C', 't', 'P', 'i', 'h'}
>>> s.clear() #清空集合的内容
>>> s
set()
三、集合的可哈希
如果一个对象是可哈希的,就要求它的哈希值,必须在其整个的生命周期中保持不变。
哈希函数hash()1.对数哈希
两个要点:(1)对一个整数去求哈希值,那么它的值永远都是等于它自身。
(2)如果两个对象的值是相等的,尽管它们是不同的对象,比如1和1.0,一个是整数一个是浮点数,它们的值是相等的,那么它们的哈希值也是相等的。
>>> hash(1)
1
>>> hash(1.0)
1
>>> hash(1.001)
2305843009213441
2.对字符串、元祖等哈希
python中大多不可变的对象(字符串、元祖)都是可哈希的,
而那些可变对象(列表、集合)则是不可哈希的。
可哈希才可以作为字典的键和集合的元素,列表不可哈希,因此不能作为字典的键和集合的元素
>>> hash("FishC") #字符串可哈希
5879751725848875285
>>> hash([1,2,3]) # 列表不可哈希
Traceback (most recent call last):
File "<pyshell#35>", line 1, in <module>
hash([1,2,3])
TypeError: unhashable type: 'list'
>>> hash((1,2,3)) #元祖可哈希
2528502973977326415
>>> {"Python":520,"FishC":1314} #字典
{'Python': 520, 'FishC': 1314}
>>> {[1,2,3]:"FishC"} #列表不可哈希会变错,不能作为字典的键
Traceback (most recent call last):
File "<pyshell#38>", line 1, in <module>
{[1,2,3]:"FishC"}
TypeError: unhashable type: 'list'
>>> {"Python","FishC",520,1314} #集合
{520, 1314, 'FishC', 'Python'}
>>> {"Python","FishC",520,1314,[1,1,2]} #列表不可哈希,因此不能作为集合的元素
Traceback (most recent call last):
File "<pyshell#41>", line 1, in <module>
{"Python","FishC",520,1314,[1,1,2]}
TypeError: unhashable type: 'list'
3.frozenset()集合嵌套
错误做法:
>>> x={1,2,3}
>>> y={x,4,5} #集合是可变的,不可哈希,不能作为集合的元素,所以不可嵌套
Traceback (most recent call last):
File "<pyshell#43>", line 1, in <module>
y={x,4,5}
TypeError: unhashable type: 'set'
使用frozenset()进行嵌套
>>> x={1,2,3}
>>> x=frozenset(x)
>>> y={x,4,5}
>>> y
{frozenset({1, 2, 3}), 4, 5}
课后题:
1.请问下面代码会打印 True 还是 False 呢?
>>> s1 = set([1, 1, 2, 3, 5])
>>> s2 = frozenset([1, 1, 2, 3, 5])
>>> s1 == s2
答:True。
解析:虽然一个是可变集合,一个是不可变(冻结)集合,但它们包含的元素是一样的。但注意,如果是拿相同元素的列表和元组进行比较,则结果会是 False。
>>> [1, 2, 3, 4, 5] == (1, 2, 3, 4, 5)
False
2.既然有了 set() 集合,为什么还要创造 frozenset()来冻结集合(换句话说,frozenset() 的优势是什么)?
答:这就像既有可变的列表,还是创造了不可变的元组一样,它们各自都有存在的理由。
使用冻结的集合,主要也是为了防止内容被肆意修改,起到一个保护的作用。
另外还有重要的一点,就是只有使用 frozenset 对象,才可以创建嵌套集合(因为集合内部的元素必须是可哈希的)。
使用 set 对象,无法创建嵌套集合:
>>> x = {1, 2, 3}
>>> y = {x, 4, 5}
Traceback (most recent call last):
File "<pyshell#39>", line 1, in <module>
y = {x, 4, 5}
TypeError: unhashable type: 'set'
改用 frozenset 对象,则解决问题:
>>> x = frozenset(x)
>>> y = {x, 4, 5}
>>> y
{frozenset({1, 2, 3}), 4, 5}
3.集合中,difference(*others)和 difference_update(*others) 这两个方法都是用于计算差集,那么它们有什么区别呢?
答:difference(*others) 方法是计算差集并将结果返回为一个新的集合,difference_update(*others) 方法则是直接使用新的结果更新集合。因此,前者 set 和 frozenset 对象均使用,后者仅 set 对象可用。
4.由于 frozenset 对象是不可修改的,所以我们说它也是可哈希的,对吗?
答:对的。
解析:当然可以哈希,不然怎么能利用它来实现嵌套集合。
>>> s = frozenset("1, 1, 3, 4, 5")
>>> hash(s)
5703935143154763776
5.请问集合对象的 remove(elem) 方法和 discard(elem) 方法有什么不同?
答:如果指定的元素不存在,remove() 方法将会抛出异常, discard() 方法则不会。