[读书笔记]流畅的python-字典和集合

泛映射类型

标准库中的所有映射类型都是利用dict实现的,只有
散列
的数据类型才能用作键。

可散列:

  • 如果一个对象是可散列的,在生命周期中,散列值是不变的。
  • 需要实现__hash__()方法和__qe__()方法
  • 不可变数据类型(str,bytes和数值类型)都是可散列的
  • 如果元组中的元素都是不可变的,则该元组是可散列的

setdefault和defaultdict

setdefault
在这里插入图片描述
defaultdict

import collections
dict = collections.defaultdict(list)

如果在创建defaultdict是没有指定default_factory,查询不存在的键会触发keyError,defauldict里的default_factory只会再__getitem__()里被调用(即dict[key]时会,dict.get(),dict.contains()不会)。

特殊方法__missing__

class StrKeyDict0(dict):
	def __missing__(self,key):
		if isinstance(key,str):
			raise KeyError(key)
		return self[str(key)) //如果输入的数字也算合法
	def get(self,key,default=Node):
		try:
			return self[key]
		except KeyError:
			return default
	def __contains__(self,key):
	return key in self.keys() or str(key) in self.keys()

字典的变种

  • collections.OrderDict
    popitem(last=[Ture])默认删除并返回字典的最后一个元素.move_to_end(). 可以用作LRU?
  • collections.ChaniMap:
    可以容乃数个不同的映射对象,当进行键查找操作室,这些对象会被当做一个整体被逐个查找,直到键被找到位置。这个功能在给有嵌套作用域的语言做解释器的时候很有用。
import builtins
pylookup = ChainMap(locals(), globals(), vars(builtins))
  • collections.Counter
  • collections.UserDict

不可变映射类型

需求:标准库里所有的映射类型都是可变的,但有时不能让用户错误的修改某个映射。

types模块中引入了MappingProxyType
输入:映射
输出:该映射的只读视图。
说明:虽然只是只读视图,但如果对原映射做了改动,我们通过这个视图可以观察到。

from types import MappingProxyType
d = {1:'A'}
d_proxy = MappingProxyType(d)
d_proxy[2]='x' # 会报错
d[2] = 'x' # ok,通过d_proxy可以观察到

集合

python中的集合指:set和frozenset
集合中的元素必须是可散列的,set类型本身是不可散列的,但frozenset是可以的。
s.union,s.issubset,s.issuperset,s.difference
s.discard(e) 如果s中有e这个元素,则把e移除
s.remove(e)

dict和set的背后

dict和set的效率

用in运算符在5个不同大小的haystack字典里搜索1000个元素所需的时间:
在这里插入图片描述

字典中的散列表

散列表是一个稀疏数组,散列表中的单元叫做表元(bucket)。在dict的散列表中,每个键值对都占用一个表元,每个表元有两部分,一部分是对键的引用,另一个是对值的引用。所有表元的大小一致,可以通过偏移量来读取某个表元。
python会设法保证大概有1/3的表元是空的,在快要达到阈值是,原有的散列表会被复制到一个更大的空间里。

用hash()方法计算元素键的散列值。

  1. 散列值和相等性:如果两个对象在比较时是相等的,那门他们的hash值应该相等。
  2. 散列表算法:
    在这里插入图片描述
    另外在插入新值时,Python 可能会按照散列表的拥挤程度来决定是否要重新分配内存 为它扩容。如果增加了散列表的大小,那散列值所占的位数和用作索引的位数都会随 之增加,这样做的目的是为了减少发生散列冲突的概率

dict的实现及其导致的结果

  1. 键必须是可散列的
  2. 字典在内存上开销巨大:由于字典使用了散列表,而散列表优势稀疏的,导致空间效率低。如果要存储数量巨大的记录,最好使用元组(避免了散列表耗费的空间,且无需把记录中的字段的名字在每个元组里都存一遍)
  3. 键查询很快
  4. 键的词语取决于添加顺序
  5. 向字典里添加新建可能会改变已有键的顺序

set的实现及其导致的结果

set 和 frozenset 的实现也依赖散列表,但在它们的散列表里存放的只有元素的引用 (就像在字典里只存放键而没有相应的值)。在 set 加入到 Python 之前,我们都是把字 典加上无意义的值当作集合来用的。
导致的结果同dict

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值