《Fluent Python》笔记 字典和集合
用setdefault处理找不到的键
对于如下两段代码,所实现的功能都是一样的。
1 |
|
1 |
|
相较而言,使用setdefault
来处理字典中不存在的键时,更加优雅。
用defaultdict处理找不到的键
defaultdict
是一个字典类型。对于上面代码中解决的键不存在问题,我们可以用defaultdict
类型解决。
1 |
|
当表达式my_dd[key]
中键key
不存在时,会进行如下步骤:
(1) 调用list()
来建立一个新列表。
(2) 把这个新列表作为值, key
作为它的键, 放到my_dd
中。
(3) 返回这个列表的引用。
特殊方法_missing_
所有的映射类型(如dict
)在处理不存在的键时,都会调用到__missing__
方法。
下面这个示例是定义了一个StrKeyDict0
类,在查询过程中会将非字符串的键转换成字符串。
1 |
|
代码中__missing__
方法只会被__getitem__
方法调用,即当d[k]
中k
键不存在时会被调用。而get
或者__contains__
(in 运算符会用调用这个方法) 这些方法遇到不在存在键时则不会被调用。 所以为了能满足程序需求,上述代码中重写了get
和__contains__
方法,使其能够应对键为非字符串的情况。
字典的变种
collections.defaultdict
在构造时可以提供一个可调用对象(如上述代码中的
list
),当d[k]
中k
不存在时会被调用并返回某种默认值(如k:[]
)。collections.OrderedDict
这个类型在添加键的时候会保持顺序, 因此键的迭代次序总是一致的。
OrderedDict
的popitem
方法默认删除并返回的是字典里的最后一个元素, 但是如果像my_odict.popitem(last=False)
这样调用它, 那么它删除并返回第一个被添加进去的元素。collections.ChainMap
这个类型可以容纳数个不同的映射对象, 然后在进行键查找操作的时候,这些对象会被当作一个整体被逐个查找,直到键被找到为止。
collections.Counter
这个类型会给键准备一个整数计数器。 每次更新一个键的时候都会增加这个计数器。
most_common([n])
会按照次序返回映射里最常见的n
个键和它们的计数。1
2
3
4
5
6
7
8>>> ct = collections.Counter('abracadabra')
>>> ct
Counter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
>>> ct.update('aaaaazzz')
>>> ct
Counter({'a': 10, 'z': 3, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
>>> ct.most_common(2)
[('a', 10), ('z', 3)]colllections.UserDict
跟
OrderedDict、 ChainMap 和 Counter
这些开箱即用的类型不同,UserDict
是让用户继承写子类的。当我们需要创建自定义映射类型时,通过继承UserDict类比继承dict更方便。
不可变映射类型
标准库中的所有映射类型都是可变的,即可以修改某个映射。在types
模块中引入了一个封装类名叫MappingProxyType
,一个映射对象通过这个类后,会得到一个只读的映射视图(无法通过映射视图修改原映射,除非直接对原映射进行修改)。
1 |
|
集合
集合本质是许多唯一对象的聚集。因此集合可用于序列对象的去重。
集合中元素必须是可散列的。set
类型本身是不可散列的,frozenset
类型本身是可散列的。
给定两个集合a
和 b
, 返回的是它们的合集,
得到的是交集, 而 a - b
得到的是差集。
由于散列表的引入,集合的查找功能非常快。
集合的字面量形如{1,2,3}
,空集必须写成set()
而非{}
(Python会认为{}
是空字典)。
集合操作
语法 | 描述 |
---|---|
a & b | 返回集合a和集合b的交集 |
a | b | 返回集合a和集合b的并集 |
a - b | 返回集合a和集合b的差集 |
a ^ b | 返回集合a和集合b的对称差集 |
a.isdisjoint(b) | 查看集合a和集合b是否不相交(没有共同元素) |
c in a | 元素c是否属于集合a |
a <= b / a >= b | 集合a是否为集合b的子集/父集 |
a < b / a > b | 集合a是否为集合b的真子集/真父集 |
其他方法:a.add(c)、a.clear()、a.copy()、a.discard(c)(如果 a 里有 c 这个元素的话, 把它移除)、a.pop()、a.remove(c)等
a、b为集合,c为元素。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!