流畅的Python读书笔记 --- 第三章 字典和集合

近期在读“流畅的Python”这本书,想把自己的读书笔记分享给大家,希望能帮到也对这本书感兴趣但是没时间看的各位。(文章中大部分的话和图片摘录总结自“流畅的Python”一书,以及python官方网站)

章节概述:本章通过深入探讨散列表的原理,介绍了字典和集合两种类型。
章节结构

  • 泛映射类型
  • 字典推导
  • 常见的映射方法
  • 映射的查询
  • 字典的变种
  • 不可变映射类型
  • 集合
  • 字典VS集合

具体内容

  • 泛映射类型

映射类型:标准库里的所有映射类型都是利用dict实现的,因为他们有一个共同的限制,只有可散列的数据类型才能用作这些映射里的
可散列的数据类型:可散列就是可hash,一个可散列数据类型的对象,在其生命周期中,它的散列值是不变的。
映射类型所需要的基本接口:collections.abc模块中定义,其中包括MutableMapping, 继承自Mapping,继承自(Container,Iterable和Sized),可以和isinstance用来判断某个数据是不是广义上的映射类型
注:非抽象映射类型没有集成这些抽象基类,而是对dict(Built-in Types)和collections.UserDict类的扩展。

  • 字典推导 dictcomp

从任何以键值对作为元素的可迭代对象中创建出字典。
形式:dictionary_variable = {arg_one: arg_two for arg_one, arg_two in ITERABLE_DATA }

  • 常见的映射方法

流畅的Python读书笔记 --- 第三章 字典和集合_第1张图片

  • 映射的查询

关于查询,dict本身提供get方法获取键值对应的值。但如若键值不存在呢?
情况一,查找键,并插入新值 --- setdefault:
字典d[k]不能找到正确的键时,Python会抛出异常,当然我们可以用d.get(k,default)来给找不到键的情况一个默认返回值。但是这些都不是最佳方法,我们可以用setdefault来解决,尤其是在通过查找插入新值时,比如一个记录单词位置的例子,如果第一次碰到的单词,自然会找不到键值,我们可以通过d.setdefault(key, []).append(value)来处理这种情况,这行代码的意思时,我们查找单词的时候,如果单词不存在,我们把单词和一个空列表放进映射,然后返回这个空列表。
情况二,查找键对应的值 ---- defaultdict & missing
如果不是查找且插入新值,而是单纯的查找中某个键没有映射值的情况,我们也希望获得一个默认读取值。这种情况我们有两种方法,一是用defaultdict,二是自定义dict子类,然后自定义子类的missing特殊方法。

  1. 创建defaultdict对象,给构造方法提供一个可调用对象,这个调用对象会在getitem找不到键时被调用,返回某种默认值。这个生成默认值的可调用对象存放在名为default_factory的实例属性里。

这个default_factory只在getitem里调用,比如d[k]会返回这个对象生成的默认值,但是d.get(k)还是会返回None。

  1. dict本身虽然没有定义missing,但是如果getitem没有找到键,Python会自动调用missing。所以如果一个类继承了dict,可以自定义missing特殊方法来处理查询中找不到的情况。
  • 字典的变种
映射类型 特点 应用场景
collections.OrderedDict 添加键的时候保持顺序
collections.ChainMap 容纳数个不同的映射对象,进行键查找时,这些对象被当做一个整体被逐个查找 用来给嵌套作用域的语言做解释器时,代表一个作用域的上下文
collections.Counter 给键准备整数计数器,每次更新一个键,计数器会增加 用于给可散列表对象技术
collections.UserDict 把标准dict用Python又实现了一遍,继承自MutableMapping 让用户继承写子类
  • 不可变映射类型

标准库里所有映射类型都是可变的,不过Python3.3开始,types模块中引入了一个封装类MappingProxyType,如果给这个类一个而映射,他会返回一个只读的映射视图。不过这个只读视图是动态的,原映射改变时,它可以观察到,但是外界无法改变这个视图,这就实现了单向改动,我们可以把包装后不可变的映射展现给用户。

  • 集合

集合,Python中的set以及frozenset,就是许多唯一对象的聚集。集合中的元素必须是可散列的,但是set类型本身时不可散列的,到那时frozenset是可散列的。
中辍运算符:a|b(合集), a&b(交集), a-b(差集)
集合字面量:{val1, val2...} / 空集set()
集合推导setcomps: {expression(x) for x in ITERABLE_DATA}
集合操作:
集合数学运算
流畅的Python读书笔记 --- 第三章 字典和集合_第2张图片

  • 字典和集合

字典和集合在Python中是速度很快的两个类型,原因依赖于他们背后的散列表。
散列表:稀疏数组(有空白元素的数组)。散列表中的单元叫做表元(bucket)。在dict的散列表中,每个键值对都占用一个表元,每个表元都有两个部分,对键的引用,对值的引用。
字典和集合对比:

特点 字典 集合
可散列 键必须可散列 元素必须可散列
内存 开销大,空间效率低,因为散列表稀疏 耗内存
查询
次序 键次序,取决于添加顺序和散列冲突的情况 元素顺序取决于被添加到集合里的次序
添加元素 可能改变已有键顺序,所以迭代和修改不要同时进行 可能改变元素已有顺序

你可能感兴趣的:(python,读书笔记)