一、概述

映射类型(Mapping Types)是一种关联式的容器类型,它存储了对象与对象之间的映射关系。

字典(dict)是Python中唯一的映射类型,它是存储了一个个 键值对(由 映射到 )的关联容器。其中,(key)必须是可哈希的Python对象,而 (value)可以是任何Python对象。在功能上,Python中的字典类似于C++中的map。

Python中最强大、最灵活的数据类型当属 列表字典,以下是对这两种数据类型的简单比较:

比较点 列表 字典
表示方法 [],[1, 2] {},{'a': 1, 'b': 2}
访问元素的方式 索引
有序性 有序 无序
可变性 可变 可变
可操作性 操作丰富 操作丰富
表征的数据结构 数组、堆栈、队列等 哈希表等

二、操作

字典支持的主要操作如下:

操作 说明
class dict(other) 创建字典(other可以是字典、(key, value)对的迭代器或关键字参数)
dict.fromkeys(seq[, value]) 创建字典:用序列seq中的元素作为键,值全为value(未指定,则默认为None)
len(d) 返回字典d的长度(即d中元素的个数)
d[key] 如果键key在字典d中,则返回其中key对应的值;否则抛出KeyError异常
d[key] = value 设置d[key]的值为value(存在则修改,不存在则添加)
del d[key] 如果键key在字典d中,则从字典d中删除d[key];否则抛出KeyError异常
key in d 如果key在字典d中,返回True;否则,返回False
key not in d 如果key在字典d中,返回False;否则,返回True
iter(d) 同iterkeys()
d.clear() 删除字典d中的所有元素
d.copy() 返回字典d的浅拷贝
d.get(key[, default]) 如果key在字典d中,则返回d[key];否则返回default(未指定,则默认为None)
d.has_key(key) 同key in d(推荐使用key in d)
d.items() 返回包含字典d中的(key, value)对的列表
d.iteritems() 迭代版的items():返回迭代器
d.iterkeys() 迭代版的keys():返回迭代器
d.itervalues() 迭代版的values():返回迭代器
d.keys() 返回包含字典d中的键的列表
d.pop(key[, default]) 如果key在字典d中,则返回并删除d[key];否则返回default(未指定,则抛出KeyError异常)
d.popitem() 返回并删除字典d中的任意一个元素(如果d为空,则抛出KeyError异常)
d.setdefault(key[, default]) 如果key在字典d中,则返回d[key];否则执行d[key] = default,并返回default(未指定,则默认为None)
d.update([other]) 将other中的(key, value)对添加到字典d中(other可以是字典、(key, value)对的迭代器或关键字参数)
d.values() 返回包含字典d中的值的列表
d.viewitems() 返回字典d的元素视图
d.viewkeys() 返回字典d的键视图
d.viewvalues() 返回字典d的值视图

以上操作的示例如下:

  1. >>> a = {'one': 1, 'two': 2, 'three': 3}
  2. >>> b = dict(one=1, two=2, three=3)
  3. >>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
  4. >>> d = dict({'three': 3, 'one': 1, 'two': 2})
  5. >>> a == b == c == d
  6. True
  7. >>> d = dict.fromkeys(['a', 'b', 'c'])
  8. >>> d
  9. {'a': None, 'c': None, 'b': None}
  10. >>> d = dict.fromkeys(['a', 'b', 'c'], 6)
  11. >>> d
  12. {'a': 6, 'c': 6, 'b': 6}
  13. >>> len(d)
  14. 3
  15. >>> d.clear()
  16. >>> d
  17. {}
  18. >>> d = a.copy()
  19. >>> d
  20. {'one': 1, 'three': 3, 'two': 2}
  21. >>> d['three']
  22. 3
  23. >>> d['four'] = 4
  24. >>> d
  25. {'four': 4, 'one': 1, 'three': 3, 'two': 2}
  26. >>> del d['one']
  27. >>> d
  28. {'four': 4, 'three': 3, 'two': 2}
  29. >>> 'four' in d, 'four' not in d
  30. (True, False)
  31. >>> d.has_key('four')
  32. True
  33. >>> d.get('one'), d.get('one', 10)
  34. (None, 10)
  35. >>> for k in d:
  36. ... print k,
  37. ...
  38. four three two
  39. >>> for k in iter(d):
  40. ... print k,
  41. ...
  42. four three two
  43. >>> for k in d.keys():
  44. ... print k,
  45. ...
  46. four three two
  47. >>> for k in d.iterkeys():
  48. ... print k,
  49. ...
  50. four three two
  51. >>> for k in d.viewkeys():
  52. ... print k,
  53. ...
  54. four three two
  55. >>> for v in d.values():
  56. ... print v,
  57. ...
  58. 4 3 2
  59. >>> for v in d.itervalues():
  60. ... print v,
  61. ...
  62. 4 3 2
  63. >>> for v in d.viewvalues():
  64. ... print v,
  65. ...
  66. 4 3 2
  67. >>> for i in d.items():
  68. ... print i,
  69. ...
  70. ('four', 4) ('three', 3) ('two', 2)
  71. >>> for i in d.iteritems():
  72. ... print i,
  73. ...
  74. ('four', 4) ('three', 3) ('two', 2)
  75. >>> for i in d.viewitems():
  76. ... print i,
  77. ...
  78. ('four', 4) ('three', 3) ('two', 2)
  79. >>> d.setdefault('two')
  80. 2
  81. >>> d
  82. {'four': 4, 'three': 3, 'two': 2}
  83. >>> d.setdefault('one', 1)
  84. 1
  85. >>> d
  86. {'four': 4, 'one': 1, 'three': 3, 'two': 2}
  87. >>> d.update(five=1)
  88. >>> d
  89. {'four': 4, 'one': 1, 'five': 1, 'three': 3, 'two': 2}
  90. >>> d.update({'six': 6})
  91. >>> d
  92. {'four': 4, 'five': 1, 'two': 2, 'six': 6, 'three': 3, 'one': 1}
  93. >>> d.pop('four')
  94. 4
  95. >>> d
  96. {'five': 1, 'two': 2, 'six': 6, 'three': 3, 'one': 1}
  97. >>> d.popitem()
  98. ('five', 1)
  99. >>> d
  100. {'two': 2, 'six': 6, 'three': 3, 'one': 1}

三、字典特性

1、有序与无序

从概念上讲,字典提供了这样一种抽象:容器中的元素之间完全独立(于是也没有先后顺序),“键”是访问元素的唯一方式。在这种 抽象层面 上,字典是 无序 的。

从实现上讲,字典其实是由 哈希表 实现的。而哈希表的基本思想是:通过 哈希函数(hash function)将“键”转换为“索引”,再使用“索引”去访问 连续列表(如C中的数组)中的元素。由此可知,在哈希表中:一方面,元素本质上是存储在一个连续列表中的,因此是 有序 的;另一方面,用户无法确定元素在连续列表中的实际位置(只能使用“键”去访问元素,而“键”与“索引”的映射关系是由哈希函数在内部指定的),因此又是 无序 的。

因此在 实现层面 上,字典同时具备了 无序有序 的特点:

  • 无序体现在:字典中元素的排列顺序与添加顺序无关
  • 有序体现在:在字典保持不变的情况下,字典中元素的排列顺序是固定的

上图对应的示例如下:

  1. # 无序
  2. >>> d = {}
  3. >>> d['a'] = 1
  4. >>> d
  5. {'a': 1}
  6. >>> d['b'] = 2
  7. >>> d
  8. {'a': 1, 'b': 2}
  9. >>> d['c'] = 3
  10. >>> d
  11. {'a': 1, 'c': 3, 'b': 2}
  12. # 有序
  13. >>> for k in d: # 键的顺序固定
  14. ... print k,
  15. ...
  16. a c b
  17. >>> for v in d.values(): # 值的顺序固定
  18. ... print v,
  19. ...
  20. 1 3 2
  21. >>> for i in d.items(): # 元素的顺序固定
  22. ... print i,
  23. ...
  24. ('a', 1) ('c', 3) ('b', 2)

2、字典的键

字典的键具有以下特性:

1)可哈希的(hashable

只有 可哈希的 对象才能作为字典的键,一个可哈希的对象必须满足以下两个条件:

  • 该对象在其生命周期内有一个不变的哈希值(需要实现__hash__()方法)
  • 该对象是可比较的(需要实现__eq__()__cmp__()方法)

Python中可哈希的对象有:

  • 数值、字符串,以及只含有数值或字符串的元组
  • 用户自定义类的实例(默认是可哈希的,也可以通过实现__hash__()__cmp__()来修改默认行为)

2)哈希等价键

假设有字典d的两个键:keyA和keyB,我们称keyA和keyB是 哈希等价键(自己杜撰的名词),如果keyA和keyB满足以下两个条件:

  • hash(keyA) == hash(keyB)
  • cmp(keyA, keyB) == 0

如果keyA和keyB是哈希等价键,那么它们将被视为完全相同的两个键,于是d[keyA]和d[keyB]会指向同一个字典元素。

例如,1和1.0就满足上述两个条件,因此是哈希等价键:

  1. >>> hash(1), hash(1.0)
  2. (1, 1)
  3. >>> cmp(1, 1.0)
  4. 0
  5. >>> d = {}
  6. >>> d[1] = 'int 1'
  7. >>> d
  8. {1: 'int 1'}
  9. >>> d[1.0] = 'float 1'
  10. >>> d
  11. {1: 'float 1'}

对于用户自定义的类实例,默认情况下(即没有实现__hash__()__cmp__()时),hash(...)和cmp(...)的结果与 id() 有关(参考 hashable__cmp__())。默认情况下,一个自定义类的任意两个实例都不是哈希等价键:

  1. >>> class A: pass
  2. ...
  3. >>> a1 = A()
  4. >>> a2 = A()
  5. >>> hash(a1), hash(a2)
  6. (-1064359592, -1064359600)
  7. >>> cmp(a1, a2)
  8. 1
  9. >>> d = {}
  10. >>> d[a1] = 'a1'
  11. >>> d
  12. {<__main__.A instance at 0x8f2958c>: 'a1'}
  13. >>> d[a2] = 'a2'
  14. >>> d
  15. {<__main__.A instance at 0x8f2958c>: 'a1', <__main__.A instance at 0x8f2950c>: 'a2'}

如果想要让同一个类的任意两个实例都是哈希等价键,则可以参考以下示例:

  1. >>> class A:
  2. ... def __hash__(self):
  3. ... return hash(A)
  4. ... def __cmp__(self, other):
  5. ... return cmp(self.__hash__(), other.__hash__())
  6. ...
  7. >>> a1 = A()
  8. >>> a2 = A()
  9. >>> hash(a1), hash(a2)
  10. (-1064346499, -1064346499)
  11. >>> cmp(a1, a2)
  12. 0
  13. >>> d = {}
  14. >>> d[a1] = 'a1'
  15. >>> d
  16. {<__main__.A instance at 0x8f64a4c>: 'a1'}
  17. >>> d[a2] = 'a2'
  18. >>> d
  19. {<__main__.A instance at 0x8f64a4c>: 'a2'}

类似地,如果想要让一个类的任意一个实例与整数1成为哈希等价键,则可以按照以下方式实现:

  1. >>> class A:
  2. ... def __hash__(self):
  3. ... return 1
  4. ... def __cmp__(self, other):
  5. ... return cmp(self.__hash__(), other.__hash__())
  6. ...
  7. >>> a = A()
  8. >>> hash(1), hash(a)
  9. (1, 1)
  10. >>> cmp(1, a)
  11. 0
  12. >>> d = {}
  13. >>> d[1] = 'int 1'
  14. >>> d
  15. {1: 'int 1'}
  16. >>> d[a] = 'instance a'
  17. >>> d
  18. {1: 'instance a'}

四、字典视图

从2.7版本开始,Python中引入了字典视图(Dictionary views)。字典视图 是字典的 动态视图:它们会与字典保持同步,实时反应出字典的变化。字典视图共有3种:键视图(Keys views)、值视图(Values views)和 元素视图(Items views),它们分别由dict.viewkeys()、dict.viewvalues()和dict.viewitems()三个函数返回。

所有的字典视图都支持以下操作:

操作 说明
len(dictview) 返回字典的长度
iter(dictview) 返回(键、值、元素)迭代器
x in dictview 判断x是否为(键、值、元素)的成员

此外,因为字典的键是 唯一可哈希的,所以 键视图 还支持 类似集合(set-like)的操作。如果字典的值是 可哈希的,那么 元素视图 也支持这些操作:

操作 说明
dictview & other 求交集
dictview | other 求并集
dictview - other 求差集
dictview ^ other 求对称差集

关于字典视图的示例,请参考 Dictionary view objects

五、应用

1、模拟switch-case语句

以下是C中一个使用switch-case语句的示例:

  1. int select(char c)
  2. {
  3. int num = -1;
  4. switch (c)
  5. {
  6. case 'a':
  7. num = 1;
  8. break;
  9. case 'b':
  10. num = 2;
  11. break;
  12. case 'c':
  13. num = 3;
  14. break;
  15. default:
  16. num = 0;
  17. break;
  18. }
  19. return num;
  20. }

Python中没有提供switch-case语句,但使用字典可以轻松实现类似上面的功能:

  1. d = {'a': 1, 'b': 2, 'c': 3}
  2. # 普通版本
  3. def select1(c):
  4. num = -1
  5. if c not in d:
  6. num = 0
  7. else:
  8. num = d[c]
  9. return num
  10. # 惊呆版本
  11. def select2(c):
  12. return d.get(c, 0)

2、稀疏矩阵

使用元组作为字典的键,可以构建类似稀疏矩阵的数据结构:

  1. >>> matrix = {}
  2. >>> matrix[(2, 3, 4)] = 88
  3. >>> matrix[(7, 8, 9)] = 99
  4. >>>
  5. >>> matrix
  6. {(2, 3, 4): 88, (7, 8, 9): 99}
  7. >>>
  8. >>> x, y, z = 2, 3, 4
  9. >>> matrix[(x, y, z)]
  10. 88

3、符号表

实际上,Python本身就在内部大量使用了字典,一个典型的应用就是符号表:

  1. >>> locals() # 局部符号表
  2. {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}
  3. >>> globals() # 全局符号表
  4. {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}

Python基础:映射(字典)的更多相关文章

  1. python基础之字典dict和集合set

    作者:tongqingliu 转载请注明出处:http://www.cnblogs.com/liutongqing/p/7043642.html python基础之字典dict和集合set 字典dic ...

  2. Python基础数据类型-字典(dict)

    Python基础数据类型-字典(dict) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客使用的是Python3.6版本,以及以后分享的每一篇都是Python3.x版本的哟 ...

  3. python基础之字典、集合

    一.字典(dictionary) 作用:存多个值,key-value存取,取值速度快 定义:key必须是不可变类型,value可以是任意类型 字典是一个无序的,可以修改的,元素呈键值对的形式,以逗号分 ...

  4. Python基础知识---字典

    现在在实习期间,好久没用Python了,今天在做Java项目时用的HashMap让我联想到了Python中的字典,就写一些Python字典的知识吧,复习复习. 字典:  key --> valu ...

  5. python基础5 字典

    一.字典 字典是python的基础数据类型之一:字典可以存储大量的数据,关系型数据. 同样他也是python中唯一的映射类的数据类型. 数据类型的分类: 可变的(不可哈希)数据类型:list,dict ...

  6. Python基础__字典、集合、运算符

    之前讨论的字符串.列表.元组都是有序对象,本节则重点讨论无序对象:字典与集合.一.字典 列表是Python中的有序集合,列表中的序指的是列表中的元素与自然数集形成了一个一一对应的关系.例如L=['I' ...

  7. python基础类型—字典

    字典 字典是python中唯一的映射类型,采用键值对(key-value)的形式存储数据.python对key进行哈希函数运算,根据计算的结果决定value的存储地址,所以字典是无序存储的,且key必 ...

  8. python基础之字典以及增删改查

    字典:字典是python中唯一的一个映射类型,主要形式为 dic = {key1:value,key2:value2,....} 字典中key的值是唯一的,主要关系到HASH算法,并且key的值必须是 ...

  9. Python基础系列----字典、基本语句

    1.定义                                                                                               映 ...

  10. python基础类型(字典:dict)

    字典的介绍: 字典(dict)Python中唯一的一个映射类型.他是以{}括起来的键值对组成,在dict中key是唯一的.在保存的时候,根据key来计算出一个内存地址,然后将key-value保存到这 ...

随机推荐

  1. Android开发(二十四)——数据存储SharePreference、SQLite、File、ContentProvider

    Android提供以下四种存储方式: SharePreference SQLite File ContentProvider Android系统中数据基本都是私有的,一般存放在“data/data/程 ...

  2. 20个最漂亮的基于WordPress的企业网站

    20个最漂亮的基于WordPress的企业网站 每个人都知道很好很强大的WordPress是开源的,并且有一个很强的的团队和更强大的支持社区.它被世界上的广大设计师.程序员和商业人员广泛使用.它已经成 ...

  3. Python: 收集所有命名参数

    有时候把Python函数调用的命名参数都收集到一个dict中可以更方便地做参数检查,或者直接由参数创建attribute等.更简单的理解就是def foo(*args, **kwargs): pass ...

  4. Jenkins Code Sign error: No provisioning profiles found

    === BUILD TARGET JenkinsTest OF PROJECT JenkinsTest WITH CONFIGURATION Release === Check dependencie ...

  5. 在GridView中使用radioButoon

    在GridView中使用radioButoon 方法一: <input type="radio" id='radioSelectFeed' name="radioD ...

  6. iOS touch事件单击双击区分响应

    如果您的 iPhone 应用里有个 view,既有单击操作又有双击操作.用户双击 view 时,总是先执行一遍单击的操作再执行双击的操作.所以直接判断时就会发现不能直接进入双击操作.下面是区分 tou ...

  7. .NET Framework 类库

    .NET Framework 类库 MSDN == V2.0 == .NET Framework 类库是一个由 Microsoft .NET Framework SDK 中包含的类.接口和值类型组成的 ...

  8. 给MySQL官方提交的bug report备忘

    1.  Bug #72215 When LOCK_plugin conflicts very much, one uninstall-audit-plugin operation crash  htt ...

  9. 顺序执行到来的消息 actor

    在某项目里,有个 actor 需要做一些持久化的操作,这些操作耗时比较久,理应使用异步的代码来写,但是需求又强调每次只能做一个持久化操作,后来的请求应该等待.一个显然的做法是阻塞式的写,这样就能比较简 ...

  10. 如何将 Cortana 与 Windows Phone 8.1 应用集成 ( Voice command - Natural language recognition )

    随着 Windows Phone 8.1 GDR1 + Cortana 中文版的发布,相信有很多用户或开发者都在调戏 Windows Phone 的语音私人助理 Cortana 吧,在世界杯的时候我亲 ...