SECTION 6 映射类型


字典是 Python 语言中唯一的映射类型

6.1 字典

6.1.1 概念

映射类型对象里哈希值(键) 和指向的对象(值)是一对多的关系,通常被认为是可变的哈希表。但是,Python字典不允许一个键对应多个值,字典的值是可变的,它是一个容器类型,能存储任意个数的 Python 对象,其中也包括其他容器类型。

字典类型和序列类型容器类(列表、元组)的区别是存储和访问数据的方式不同。序列类型只用数字类型的键(从序列的开始起按数值顺序索引)。映射类型可以用其他对象类型做键;一般最常见的是用字符串做键(keys)。和序列类型的键不同,映射类型的键(keys)直接,或间接地和存储的数据值相关联。

在映射类型中,我们不再用"序列化排序"的键(keys),所以映射类型中的数据是无序排列的。显然,这并不影响我们使用映射类型,因为映射类型不要求用数字值做索引以从一个容器中获取对应的数据项。可以用键(key)直接 “映射” 到值, 这就是为什么叫映射类型(“mapping type”)的原因。映射类型通常被称做哈希表的原因是字典对象就是哈希类型的。
字典是 Python 中最强大的数据类型之一。

6.1.2 核心笔记:什么是哈希表?它们与字典的关系是什么?

序列类型用有序的数字键做索引将数据以数组的形式存储。一般,索引值与所存储的数据毫无关系。还可以用另一种方式来存储数据:基于某种相关值,比如说一个字符串。我们在日常生活中一直这么做。

把人们的电话号码按照他们的姓记录在电话簿上,按照时间在日历或约会簿上添加事件,等等。在这些例子中,你的键(key)就是和数据项相关的值。哈希表是一种数据结构:它按照我们所要求的去工作。哈希表中存储的每一条数据,叫做一个值(value),是根据与它相关的一个被称作为键(key)的数据项进行存储的。键和值合在一起被称为“键-值 对”(key-value pairs)

哈希表的算法是获取键,对键执行一个叫做哈希函数的操作,并根据计算的结果,选择在数据结构的某个地址中来存储你的值。任何一个值存储的地址皆取决于它的键。正因为这种随意性,哈希表中的值是没有顺序的。你拥有的是一个无序的数据集。你所能获得的有序集合只能是字典中的键的集合或者值的集合。方法 Keys() 或 values() 返回一个列表,该列表是可排序的。 你还可以用 items()方法得到包含键、值对的元组的列表来排序。由于字典本身是哈希的,所以是无序的。哈希表一般有很好的性能, 因为用键查询相当快。

6.1.3 字典结构

Python 的字典是作为可变的哈希表实现的。一个字典条目的语法格式是 键:值。 而且,多条字典条目被包含在( { } ) 里。
{'key':'value','key2':'value2",...}

6.1.4 创建字典和给字典赋值

1.创建字典只需要把字典赋值给一个变量,不管这个字典是否包含元素:

>>> dict1 = {}
>>> dict2 = {'name': 'earth', 'port': 80}
>>> dict1, dict2
({}, {'port': 80, 'name': 'earth'})

2.用工厂方法 dict() 来创建字典,或类型转换使用

>>> fdict = dict((['x', 1], ['y', 2]))
>>> fdict
{'y': 2, 'x': 1}

3.用一个很方便的内建方法 fromkeys() 来创建一个"默认"字典, 字
典中元素具有相同的值 (如果没有给出, 默认为 None):

>>> {}.fromkeys(('x','y'),0)
{'y': 0, 'x': 0}
>>> {}.fromkeys(('x','y'),)
{'y': None, 'x': None}
6.1.5 访问字典中的值

1.要想遍历一个字典(一般用键), 你只需要循环查看它的键,用 keys()方法获取供循环使用的键值列表

for key in dict2.keys():

2.只需要用字典的名字就可以在 for 循环里遍历字典

>>> fd={}.fromkeys(('x','y','z'),0)
>>> for key in fd:
...     print 'key=%s,v=%s'%(key,fd[key])
... 
key=y,v=0
key=x,v=0
key=z,v=0

3.要得到字典中某个元素的值, 可以用字典键加上中括号来得到:

>>> dict2['name']
'earth'

当访问不存在的key,报错

>>> fd['w']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'w'
>>> fd['x']
0

避免使用不存在的key,可以使用has_key()检查

>>> fd.has_key('w')
False
>>> fd.has_key('x')
True

或使用in 或not in检查:

>>> 'w' in fd.keys()
False
>>> 'x' in fd.keys()
True
>>> 'x' in fd
True
>>> 'w' in fd
False

字典中的键必须是可哈希的(不可变的数据类型), 所以数字和字符串可以作为字典中的键, 但是列表和其他字典不行。

更新字典

>>> dict2['name'] = 'venus' # 更新已有条目
>>> dict2['port'] = 6969 # 更新已有条目
>>> print 'host %(name)s is running on port %(port)d' %dict2
host venus is running on port 6969

**用字典参数可以简化 print 语句 **

6.1.6 删除字典元素和字典

del dict2[‘name’] 删除键为“name”的条目
dict2.clear() 删除 dict2 中所有的条目
del dict2 删除整个 dict2 字典
dict2.pop(‘name’) 删除并返回键为“name”的条目

6.1.7 核心笔记:避免使用内建对象名字作为变量的标识符

你可能用 dict 作为一个字典的标识符。但是,因为 dict() 现在已成为 Python 的类型和工厂方法,重载 dict()会给你带来麻烦和潜在的 bugs。编译器允许你做这样的重载,它认为你是聪明的,知道自己正在做什么!小心。请不要用 dict, list,file, bool, str, input, len 这样的内建类型为变量命名。

6.2 映射类型操作符

6.2.1 字典的键查找操作符([ ])

键查找操作符[]是唯一仅用于字典类型的操作符,它和序列类型里单一元素的切片(slice)操作符很相象。对序列类型来说,用索引做唯一参数或下标(subscript)以获取一个序列中某个元素的值。对字典类型来说,是用键(key)查询(字典中的元素),所以键是参数(argument), 而不是一个索引(index)。键查找操作符既可以用于给字典赋值,也可以用于从字典中取值

6.2.2 (键)成员关系操作( in ,not in)

可以用 in 和 not in 操作符来检查某个键是否存在于字典中

>>> 'name' in dict2
True
>>> 'phone' in dict2
False
6.2.3 映射类型的内建函数和工厂函数
6.2.3.1 标准类型函数[type()、str()和 cmp()]

对一个字典调用 type()工厂方法,会返回字典类型, “<type ‘dict’>”.
调用str()工厂方法将返回该字典的字符串表示形式
cmp() 做字典的比较一般不是很有用

6.2.3.2 dict()

工厂函数dict()被用来创建字典。如果不提供参数,会生成空字典。当容器类型对象做为一个参数传递给方法 dict() 时很有意思。如果参数是可以迭代的,即,一个序列,或是一个迭代器,或是一个支持迭代的对象,那每个可迭代的元素必须成对出现。在每个值对中,第一个元素是字典的键、第二个元素是字典中的值。见 Python 文档里关于 dict()的例子:

>>> dict(zip(('x', 'y'), (1, 2)))
{'y': 2, 'x': 1}
>>> dict([['x', 1], ['y', 2]])
{'y': 2, 'x': 1}
>>> dict([('xy'[i-1], i) for i in range(1,3)])
{'y': 2, 'x': 1}

如果输入参数是(另)一个映射对象,比如,一个字典对象,对其调用 dict()会从存在的字典里复制内容来生成新的字典。新生成的字典是原来字典对象的浅复制版本, 它与用字典的内建方法copy() 生成的字典对象是一样的。但是从已存在的字典生成新的字典速度比用 copy()方法慢,我们推荐使用 copy()。

6.2.3.3 len()

内建函数 len()很灵活。它可用在序列、映射类型和集合上(在本章的后面我们会看到)。对字典调用 len(),它会返回所有元素(键-值对)的数目

6.2.3.4 hash()

**内建函数 hash()本身并不是为字典设计的方法,但它可以判断某个对象是否可以做一个字典的键。**将一个对象作为参数传递给 hash(), 会返回这个对象的哈希值。 只有这个对象是可哈希的,才可作为字典的键 (函数的返回值是整数,不产生错误或异常)。如果用比较操作符来比较两个数值,发现它们是相等的,那么即使二者的数据类型不同, 它们也会得到相同的哈希值。如果非可哈希类型作为参数传递给 hash()方法,会产生 TypeError 错误(因此,如果使用这样的对象作为键给字典赋值时会出错)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
6.2.4 字典类型方法
方法名字操作
dict.clear ()删除字典中所有元素
dict.copy ()返回字典(浅复制)的一个副本
dict.fromkeys (seq,val=None)创建并返回一个新字典,以 seq 中的元素做该字典的键,val 做该字典中所有键对应的初始值(如果不提供此值,则默认为 None)
dict.get(key,default=None)对字典 dict 中的键 key,返回它对应的值 value,如果字典中不存在此键,则返回 default 的值(注意,参数 default 的默认值为 None)
dict.has_key(key)如果键(key)在字典中存在,返回 True,否则返回 False. 在 Python2.2版本引入 in 和 not in 后,此方法几乎已废弃不用了,但仍提供一个可工作的接口。
dict.items()返回一个包含字典中(键, 值)对元组的列表
dict.keys()返回一个包含字典中键的列表
dict.iter()方法 iteritems(), iterkeys(), itervalues()与它们对应的非迭代方法一样,不同的是它们返回一个迭代子,而不是一个列表。
dict.pop(key[, default])和方法 get()相似,如果字典中 key 键存在,删除并返回 dict[key],如果 key 键不存在,且没有给出 default 的值,引发 KeyError 异常。
dict.setdefault(key,default=None)和方法 set()相似,如果字典中不存在 key 键,由 dict[key]=default 为它赋值。
dict.update(dict2)将字典 dict2 的键-值对添加到字典 dict
dict.values()返回一个包含字典中所有值的列表
6.2.5 字典的键

字典中的值没有任何限制
他们可以是任意 Python 对象,即,从标准对象到用户自定义对象皆可。但是字典中的键是有类型限制的。字典不允许一个键对应多个值,你必须明确一条原则:每个键只能对应一个项键必须是可哈希的
为什么键必须是可哈希的?解释器调用哈希函数,根据字典中键的值来计算存储你的数据的位置。如果键是可变对象,它的值可改变。如果键发生变化,哈希函数会映射到不同的地址来存储数据。如果这样的情况发生,哈希函数就不可能可靠地存储或获取相关的数据。选择可哈希的键的原因就是因为它们的值不能改变。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值