python—字典和集合解析

1、泛映射类型

python标准库里的所有映射类型都是利用dict来实现的,因为他们有个共同点,即只有可散列的数据类型才能用作这些映射里的键(只有键有这个要求,值并不需要可散列的数据类型)

什么叫可散列的数据类型
如果一个对象是可散列的,那么在这个对象的生命周期中,它的散列值是不变的,且这个对象需要实现**hash()**方法。另外可散列对象还需要有__qe__()方法,这样才能跟其他键作比较。

可散列类型有:str,bytes和数值类型,frozenset,元组中的元素是不可变类型的元组,用户自定义的类型的对象。

2、字典推导

DIAL_OCDES = [(86, "china"), (91, "india"), (81, "japan")]
country_code = {country: code for code, country in DIAL_OCDES}
{'china': 86, 'india': 91, 'japan': 81}

3、三种字典数据类型

dict, defaultdict, OrderedDict
后面两个数据类型是dict的变种,位于collections模块内。
dict就是我们常用的数据类型,没有什么好说的。

defaultdict
defaultdict是为了我们在某个键在映射里不存在的时候,我们也希望在通过这个键读取值得时候得到一个默认值。
这时可能有人会说那setdefault不也可以做到吗,这里要注意区别,setdefault是上面三种数据类型的方法,它是在找不到指定的键时,在字典中添加指定的键值对。

defaultdict是如何处理找不到的键的呢?
具体而言,在实例化一个defaultdict的时候,需要给构造方法提供一个可调用对象,这个可调用对象会在__getitem__碰到找不到的键的时候被调用,让__getitem__返回默认值。生成默认值的可调用对象存在名为default_factory的工厂内。
可调用对象:用户自定义的函数,内置函数,内置方法,方法,类,类的实例,生成器函数(这个我们后面会仔细说),常见的就是list,set,str。

defaultdict能这样处理的原因在于它实现了特殊方法__missing__,如果一个类继承了dict,然后为这个继承类提供了__missing__方法,那么在碰到不存在的键的时候,Python就会自动调用__missing__方法,返回默认值,而不是抛出一个KeyError异常。

OrderedDict
从它的名字就可以看出,它跟顺序有关,我们知道dict里面键的顺序是不一定的,跟我们添加键的顺序无关。而OrderedDict在添加键的时候会保持顺序。OrderedDIct的popitem方法默认删除字典里最后一个元素。

4、不可变映射类型

标准库中所有的映射类型都是可变的,types模块中引入了一个封装类名叫MappingProxyType,这个可以用来获取字典的只读实例,也就是说它只能读,不能写,修改,且它是动态的。
在这里插入图片描述

5、集合

集合的本质时是许多唯一对象的聚集,因此集合通常可用来去重。
集合中的元素必须是可散列的。
集合实现了很多基础的中缀元素符,支持取并,取交,取查,取反等。
集合也支持集合推导。

6、字典和集合的实现及其优点和限制

和java类似,字典和集合也是利用散列表实现的,它们的优缺点也是它们的实现方式所带来的。而散列表一个问题就是散列冲突。

散列表其实是一个稀疏数组,散列表里的单元称为表元,在dict的散列表中,每个键值对都占用一个表元,每个表元都有两个部分,一个是对键的引用,一个是对值得引用。因为表元的大小一致,所以可以通过偏移量来读取某个表元。

当把一个对象放入散列表的时候,python首先用hash()方法来计算这个元素值得散列值,然后在散列表中找到一个空的表元放入,在没有散列冲突的理想情况·下,一个散列值就对应一个散列表中的一个位置。

查找键的值的时候,python首先调用hash计算键的散列值,把这个值最低的几位数字当做偏移量,在散列表中查找表元,若找到的表元为空,就抛出异常,否则就查看表元中键与我们要查找额是否相等,不相等说明有散列冲突,即两个不同的键它们的散列值相同。此时散列算法会把散列值中另外再取几位数字,把新得到的数字当做索引去寻找表元,重复这个操作。

dict的优势和限制

  • 键必须是可散列的
  • 字典在内存上的开销巨大,因为字典是利用散列表实现的,散列表又必须是稀疏的,导致它在空间效率上极低。
  • 键=查询很快,O(1)
  • 键的次序取决于添加的顺序
  • 往字典里添加新键可能会改变已有键的顺序

set有类似的特点,set中散列表只存放元素的引用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值