前面两篇日志中,我们介绍了 python 的序列类型,包含字符串、列表和元组
python 序列与深浅拷贝
python 序列支持的所有操作
接下来我们就来介绍 python 映射类型
字典是 Python 语言中的一种映射类型,是一种存储哈希表结构的容器类型
字典是 Python 中最强大的数据类型之一,它存储的数据是无序的,但是一般具有很好的性能
>>> dict1 = {}
>>> dict2 = {'name': 'earth', 'port': 80}
>>> dict1, dict2
({}, {'port': 80, 'name': 'earth'})
fromkeys
字典的 fromkeys 可以将序列转换为字典,转换后的字典的 key 即是序列的元素,value 则是默认值参数
dict.fromkeys(seq[, value])
>>> seq = ('hello', 'world', 'python')
>>> dict = {}.fromkeys(seq)
>>> print(dict)
{'hello': None, 'world': None, 'python': None}
>>> dict = {}.fromkeys(seq, 'techlog')
>>> print(dict)
{'hello': 'techlog', 'world': 'techlog', 'python': 'techlog'}
>>>
字典值的访问
通过 [] 操作符可以访问字典中的值:
>>> dict1['port']
80
但需要注意的是,一旦我们试图访问不存在的键,就会报出如下错误:
>>> dict2['server']
Traceback (innermost last):
File "<stdin>", line 1, in ?
KeyError: server
遍历
可以通过 key 遍历字典:
>>> dict2 = {'name': 'earth', 'port': 80}
>>>
>>>> for key in dict2.keys():
... print 'key=%s, value=%s' % (key, dict2[key])
...
key=name, value=earth
key=port, value=80
>>>
>>> dict2 = {'name': 'earth', 'port': 80}
>>>
>>>> for key in dict2:
... print 'key=%s, value=%s' % (key, dict2[key])
...
key=name, value=earth
key=port, value=80
删除字典或元素
del dict2['name'] # 删除键为“name”的条目
dict2.clear() # 删除 dict2 中所有的条目
del dict2 # 删除整个 dict2 字典
dict2.pop('name') # 删除并返回键为“name”的条目
删除整个字典的操作不常见,通常都是删除字典中的单个元素或是清除整个字典的内容
字典的比较
python3 取消了内建的 cmp 方法,但 >、<、== 操作符仍然保留着
字典的比较时按照下面的顺序进行的:
- 比较字典长度
- 比较字典的键,键比较的顺序和 keys()方法返回键的顺序相同
- 比较字典的值,如果两个字典的长度相同而且它们的键也完全匹配,则用字典中每个相同的键所对应的值进行比较
如果上面三步均完全匹配,那么两个字典就是相等的
为了便于使用,标准库中还存在几个其他的字典类,他们都是在 dict 的基础上实现的
collections.OrderedDict
默认的 dict 类型是无序的,任何操作都不能依赖遍历 dict 时的元素顺序来进行
但有时我们确实需要一个有序的字典,这时就需要 OrderedDict 了
>>> from collections import OrderedDict
>>> d = dict([('a', 1), ('b', 2), ('c', 3)])
>>> d # dict的Key是无序的
{'a': 1, 'c': 3, 'b': 2}
>>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
>>> od # OrderedDict的Key是有序的
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
OrderedDict 默认是按照 key 插入顺序排列的,通过他的 popitem 方法以及其参数 last 可以十分方便的实现一个栈或队列
collections.ChainMap
ChainMap 可以把一组 dict 串起来并组成一个逻辑上的 dict
下面是一个利用 ChainMap 实现的参数获取程序,如果用户传入了参数则使用相应参数,否则使用默认参数:
from collections import ChainMap
import os, argparse
# 构造缺省参数:
defaults = {
'color': 'red',
'user': 'guest'
}
# 构造命令行参数:
parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user')
parser.add_argument('-c', '--color')
namespace = parser.parse_args()
command_line_args = { k: v for k, v in vars(namespace).items() if v }
# 组合成ChainMap:
combined = ChainMap(command_line_args, os.environ, defaults)
# 打印参数:
print('color=%s' % combined['color'])
print('user=%s' % combined['user'])
collections.Counter
collections.Counter 类型会给键准备一个整数计数器,每次更新一个键的时候都会增加这个计数器,他可以非常方便的用来实现一些统计任务,比如下面的统计字符串中每个字符的重复次数的统计程序:
>>> 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
colllections.UserDict 是标准 dict 的 python 实现版,其用法与结构等等都是与 dict 一模一样的,那他存在的价值是什么呢?
那是因为虽然我们可以继承标准 dict 类型来实现一个自定义的字典类,但是这些用 CPython 编写的内置类型的子类将无法覆盖其特殊方法
也就是说,在调用特殊方法时,多态的特性会失效,无论怎样都会调用标准的父类方法
因此,如果你需要定义一个自己的字典类,那只能选择继承 UserDict
欢迎关注微信公众号,以技术为主,涉及历史、人文等多领域的学习与感悟,每周三到七篇推文,只有全部原创,只有干货没有鸡汤

读书笔记
龙潭书斋
python
python核心编程
set
集合
dict
字典
frozenset