字典中的数据是无序排列的。

        映射类型也可被称做哈希表,哈希表的算法是获取键,对键执行一个叫做哈希函数的操作,并根据计算的结果,选择在数据结构的某个地址中来存储值。任何一个值存储的地址皆取决于它的键。正因为这种随意性,哈希表中的值是没有顺序的。哈希表一般有很好的性能,因为用键查询相当快。

 

一:创建字典

        1:dict()

        从Python2.2版本起,可以用工厂方法 dict() 来创建字典。

        如果不提供参数,会生成空字典。若参数是可以迭代的,如序列、迭代器,或是一个支持迭代的对象,那每个可迭代的元素必须成对出现。在每个值对中,第一个元素是字典的键、第二个元素是字典中的值。例子:

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

>>> dict(zip(('x', 'y'), (1, 2)))
{'y': 2, 'x': 1}

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

        

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

 

        从Python2.3 开始,dict()方法可以接受关键字参数字典:

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

        

2:fromkeys()

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

>>> ddict = {}.fromkeys(('x', 'y'),  -1)
>>> ddict
{'y': -1,  'x': -1}

>>> edict = {}.fromkeys(('foo', 'bar'))
>>> edict
{'foo': None,  'bar':None}

 

二:访问字典

        从Python2.2 开始,可以不必再用keys()方法获取供循环使用的键值列表了。 可以用迭代器来轻松地访问类序列对象(sequence-like objects),比如字典和文件。只需要用字典的名字就可以在 for 循环里遍历字典。

>>> 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

 

要得到字典中某个元素的值, 可以用字典的键查找操作符([ ]):

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

 

使用[ ]时,如果在这个字典中没有对应的键,将会产生一个错误:

>>> dict2['server']
Traceback (innermost last):
File "<stdin>", line 1, in ?
KeyError: server

        检查一个字典中是否有某个键,是用字典的 has_key()方法, 或者另一种比较好的方法就是从2.2 版本起用的,in 或 not in 操作符。

 

三:更新和删除字典

        1:更新

        字典的键查找操作符([ ]),既可以用于从字典中取值,也可以用于给字典赋值。如果字典中该键已经存在,则字典中该键对应的值将被新值替代。如果改键不存在,则相当于增加新条目:

>>> dict2['name'] = 'venus'           # 更新已有条目
>>> dict2['arch'] = 'sunos5'            # 增加新条目

 

        2:删除

        以下是删除字典和字典元素的例子:

del dict2['name']             # 删除键为“name”的条目

dict2.clear()                     # 删除dict2 中所有的条目

del dict2                           #删除整个dict2 字典

dict2.pop('name')            #删除并返回键为“name”的条目

 

四:字典的比较

        字典的比较不是很有用也不常见。比较算法按照以下的顺序:

        (1)比较字典长度

        如果字典的长度不同,那么用cmp(dict1, dict2) 比较大小时,如果字典 dict1 比 dict2 长,cmp()返回正值,如果 dict2 比 dict1 长,则返回负值。也就是说,字典中的键的个数越多,这个字典就越大。

        (2)比较字典的键

        如果两个字典的长度相同,那就按字典的键比较;键比较的顺序和 keys()方法返回键的顺序相同。这时,如果两个字典的键不匹配时,对这两个(不匹配的键)直接进行比较。当dict1 中第一个不同的键大于dict2 中第一个不同的键,cmp()会返回正值。

        (3)比较字典的值

        如果两个字典的长度相同而且它们的键也完全匹配,则用字典中每个相同的键所对应的值进行比较。一旦出现不匹配的值,就对这两个值进行直接比较。若dict1 比dict2 中相同的键所对应的值大,cmp()会返回正值。

        (4) 完全匹配

        到此为止,每个字典有相同的长度、相同的键、每个键也对应相同的值,则字典完全匹配,cmp函数返回0 值。

 

五:字典的键

        大多数Python对象都可以作为键;但它们必须是可哈希的对象。所有不可变的类型都是可哈希的,因此它们都可以做为字典的键。像列表和字典这样的可变类型,由于它们不是可哈希的,所以不能作为键。

        在执行中字典中的键不允许被改变。比如创建了一个字典,字典中包含一个元素(一个键和一个值)。可能是由于某个变量的改变导致键发生了改变。这时候你如果用原来的键来取出字典里的数据,会得到KeyError。现在你没办法从字典中获取该值了,因为键本身的值发生了变化。由于上面的原因,字典中的键必须是可哈希的, 所以数字和字符串可以作为字典中的键, 但是列表和其他字典不行。

 

        一个要说明的是问题是数字:值相等的数字表示相同的键。换句话来说,整型数字 1 和 浮点数 1.0 的哈希值是相同的,即它们是相同的键。

        也有一些可变对象(很少)是可哈希的,它们可以做字典的键,但很少见。举一个例子,一个实现了__hash__() 特殊方法的类。因为__hash__()方法返回一个整数,所以仍然是用不可变的值(做字典的键)。

 

        数字和字符串可以被用做字典的键,元组虽然是不可变的,但是元组也有可能包含可变对象。所以用元组做有效的键,必须要加限制:元组中只包括像数字和字符串这样的不可变参数,才可以作为字典中有效的键。

 

六:映射类型相关函数

        内建函数hash()可以判断某个对象是否可以做一个字典的键。将一个对象作为参数传递给 hash(), 会返回这个对象的哈希值。 只有这个对象是可哈希的,才可作为字典的键 (函数的返回值是整数,不产生错误或异常)。

        如果非可哈希类型作为参数传递给hash()方法,会产生TypeError 错误(因此,如果使用这样的对象作为键给字典赋值时会出错):

>>> hash([])
Traceback (innermost last): File"<stdin>", line 1, in ?
TypeError: list objects are unhashable
>>> 
>>> dict2[{}] = 'foo'
Traceback (most recent call last): File"<stdin>", line 1, in ?
TypeError: dict objects are unhashable

 

七:映射类型内建方法

        1:keys()方法,返回一个列表,包含字典中所有的键(的副本)。

        2:values()方法,返回一个列表,包含字典中所有的值(的副本)。

        3:items(),返回一个包含所有(键, 值)元组(的副本)的列表。这些方法在不按任何顺序遍历字典的键或值时很有用。

>>> dict2.keys()
['port', 'name']

>>> dict2.values()
[80, 'earth']

>>> dict2.items()
[('port', 80), ('name', 'earth')]

 

        4:dict.get(key, default=None)

        对字典dict中的键key,返回它对应的值value,如果字典中不存在此键,则返回default的值,参数default的默认值为None,所以该函数不会引发KeyError异常。该函数也不会改变字典。

 

        5:dict.pop(key [, default])

        如果字典中key键存在,删除并返回dict[key],如果key 键不存在,但是给出了default参数,则返回default。如果没有给出default且key不存在,则引发KeyError 异常。该函数有可能改变字典。

 

        6:update()方法可以用来将一个字典的内容添加到另外一个字典中。字典中原有的键如果与新添加的键重复,那么重复键所对应的原有条目的值将被新键所对应的值所覆盖。原来不存在的条目则被添加到字典中。

        7:clear()方法可以用来删除字典中的所有的条目。

>>> dict2= {'host':'earth',  'port':80}
>>> dict3= {'host':'venus',  'server':'http'}
>>> dict2.update(dict3)
>>> dict2
{'server': 'http', 'port': 80, 'host': 'venus'}
>>> dict3.clear()
>>> dict3
{}

 

        8:copy()方法返回一个字典的副本。注意这只是浅复制。

 

        9:setdefault(key [,default])是自2.0才有的内建方法, 使得代码更加简洁。它实现了常用的语法:如果字典中key存在,则不改变字典,直接返回它的值。如果所找的key在字典中不存在,则给这个键赋default并返回default,default默认为None。

>>> myDict = {'host': 'earth', 'port': 80}
>>> myDict.setdefault('port', 8080)
80

>>> myDict.setdefault('prot', 'tcp')
'tcp'

>>> myDict.items()
[('prot', 'tcp'), ('host', 'earth'), ('port', 80)]

 

        10:因keys(),items(), 和 values()方法的返回值都是列表。数据集如果很大会导致很难处理,因此iteritems(), iterkeys(), 和itervalues() 方法被添加到 Python2.2 中。这些函数与返回列表的对应方法相似,只是它们返回惰性赋值的迭代器,所以节省内存。

 

八:其他

        要避免使用内建对象名字作为变量的标识符。不要用 dict, list, file, bool, str, input, len 这样的内建类型为变量命名。

>>> print 'host %(name)s is runningon port %(port)d' %dict2
host venus is running on port 6969

        上面的print语句展示了另一种使用字符串格式符( %)的方法。用字典参数可以简化print 语句,因为这样做你只须用到一次该字典的名字,而不用在每个元素出现的时候都用元组参数表示。

呵呵