全面深入了解python(五)
1. 字典
dict类型不但在各种在各种程序里广泛使用,也是python语言的基石。模块的命名空间、实例的属性和函数的关键字参数中都可以看到字典的身影。
字典类型性能出众的原因是使用了散列表。
1.1 泛映射类型
collections.abc模块中有Mapping和mutableMapping这两个抽象基类。它们的作用是为dict和其他类似的类型定义形式接口。
Collections.abc中的MutableMapping和它的超类UML类图,箭头从子类指向超类,抽象类和抽象方法的名称以斜体显示。
非抽象映射类型一般不会直接继承这些抽象基类,他们会直接对dict或是collections.User.Dict进行扩展。还可以跟isinstance一起被用来判定某个数据是不是广义上的映射类型:
>>> from collections import abc
>>> my_dict = {}
>>> isinstance(my_dict,abc.Mapping)
True
标准库里的所有映射类型都是利用dict来实现的,因此它们有个共同的限制,即只有可散列的数据类型才能用作这些映射里的键,值没有要求。
可散列类型:如果一个对象是可散列的,那么在这个对象的生命周期中,它的散列值是不变的,而且这个对象需要实现__hash__()
方法。另外可散列对象还要有__qe__()
方法,这些才能和其他键做比较。如果两个可散列对象是相等的,那么它们的散列值一定是一样的。
原子不可变数据类型(str、bytes和数值类型)都是可散列类型,frozenset也是可散列的。当元组包含的所有元素都是可散列类型的情况下,它才是可散列的。
>>> tt = (1,2,(30,40))
>>> hash(tt)
8027212646858338501
>>> tl = (1,2,[30,40])
>>> hash(tl)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> tf = (1,2,frozenset([30,40]))
>>> hash(tf)
985328935373711578
根据这些定义,字典提供了很多构造方法!
>>> a = dict(one=1,two=2,three=3)
>>> b = {'one':1,'two':2,'three':3}
>>> c = dict(zip(['one','two','three'],[1,2,3]))
>>> d = dict([('two',2),('one',1),('three',3)])
>>> e = dict({'three':3,'one':1,'two':2})
>>> a == b == c == d == e
True
1.2 字典推导
前面有列表推导,现在概念移植到字典上。字典推导可以从任何以键值对作为元素的可迭代对象中构建出字典。
>>> DIAL_CODES = [
... (86,'China'),
... (81,'India'),
... (1,'United States'),
... (62,'Indonesia'),
... (55,'Brazil'),
... (92,'Pakistan'),
... (880,'Bangladesh'),
... (234,'Nigeria'),
... (7,'Russia'),
... (81,'Japan')
... ]
#字典推导式,这里是以country为键
>>> country_code = {country:code for code,country in DIAL_CODES}
>>> country_code
{'China': 86, 'India': 81, 'United States': 1, 'Indonesia': 62, 'Brazil': 55, 'Pakistan': 92, 'Bangladesh': 880, 'Nigeria': 234, 'Russia': 7, 'Japan': 81}
#字典推导式,这里是以code为键,并加入了限定条件
>>> {code:country.upper() for country , code in country_code.items() if code < 66}
{1: 'UNITED STATES', 62: 'INDONESIA', 55: 'BRAZIL', 7: 'RUSSIA'}
如果列表推导的概念你已经了解,发现字典推导很好理解。