一、基础复习

二、集合中元素的基本操作

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() 方法则不会。