字典是Python中唯一的映射类型。字典对象是可变的容器类型。
字典是用{}括起来的key,value对。字典中的数据是无序排列的,因此不能切片。
字典的创建
- >>> d = {} # 创建空字典
-
>>> d
-
{}
-
>>> d1 = {'name':'earth', 'port':80, 'age':12, 'age':23} # 用key:value的方式创建字典
-
>>> d1
-
{'age': 23, 'name': 'earth', 'port': 80} # 相同的key最后只能出现一个。
-
>>> dict(([1, 'hi'],[2,'hello'])) # 用dict函数生成字典
-
{1: 'hi', 2: 'hello'}
-
>>> dict(x=1,y=2) # dict函数有多个重载,下面会介绍
-
{'y': 2, 'x': 1}
-
>>> dict.fromkeys(('x','y'),-1) # 用dict的fromkeys函数生成字典, 这里-1为默认值
-
{'y': -1, 'x': -1}
-
>>> {}.fromkeys(('x','y')) # 不指定默认值时,为None
-
{'y': None, 'x': None}
-
>>>
关于dict()函数和fromkeys()函数,后面会说。
关于字典的key:
i)一个key只会有一个对应值,即使你在初始化时指定多个值,但最终也只对应一个值。上面的字典d1就说明了这个问题
ii)key必须是可hash的。不可变的类型都是可hash的,如数字和字符串。也因此字典的key不能为列表和字典。如果元组的元素是:数字、字符串或只包含数字和字符串的元组,那这种元组也可以作为key。可见这里关键的还是可不可变。
字典的访问
- >>> d = {'name':'earth', 1:'first', ('temp','tuple'):'tuple'}
-
>>> d['name'] # 用dict[key]的方式来访问对应的value
-
'earth'
-
>>> d[1]
-
'first'
-
>>> d[('temp','tuple')]
-
'tuple'
-
>>> for key in d.keys(): # keys()函数返回字典的key的列表
-
... print '[',key,',',d[key],']'
-
...
-
[ 1 , first ]
-
[ ('temp', 'tuple') , tuple ]
-
[ name , earth ]
-
>>> for key in d: # 字典本身也可以作为一个迭代器来迭代
-
... print 'key=%s, value=%s' % (key, d[key])
-
...
-
key=1, value=first
-
key=('temp', 'tuple'), value=tuple
-
key=name, value=earth
-
>>> d[2] # 若访问字典中不存在的key,就会抛出KeyError异常
-
Traceback (most recent call last):
-
File "", line 1, in <module>
-
KeyError: 2
-
>>>
可见字典的访问就是用dict[key]的方式访问单个元素,用dict.keys()或dict本身来循环访问字典中所有key。
字典的更新
更新包括:字典中添加(key,value)对、修改已存在的数据项、删除存在的数据项
- >>> d = {'name':'earth', 1:'first', ('temp','tuple'):'tuple'}
-
>>> d['ans'] = 42 # 用d[key]=value的方式直接插入数据项
-
>>> d
-
{1: 'first', ('temp', 'tuple'): 'tuple', 'name': 'earth', 'ans': 42}
-
>>> d['name'] = 'mars' # 用d[key]=value的方式直接改变数据项
-
>>> d
-
{1: 'first', ('temp', 'tuple'): 'tuple', 'name': 'mars', 'ans': 42}
-
>>> del d[('temp','tuple')] # 用del d[key]的方式删除数据项
-
>>> d
-
{1: 'first', 'name': 'mars', 'ans': 42}
-
>>> a = d.pop('name') # 用pop(key)函数,返回d[key],并删除d[key]
-
>>> a
-
'mars'
-
>>> d
-
{1: 'first', 'ans': 42}
-
>>> d.clear() # clear()函数删除所有数据项
-
>>> d
-
{}
-
>>> del d # 删除字典本身
-
>>> d
-
Traceback (most recent call last):
-
File "", line 1, in <module>
-
NameError: name 'd' is not defined
-
>>>
因此用dict[key]=value的方式添加或更新数据项,用del dict[key]的方式删除数据项,或用pop(key)函数删除dict[key],并返回dict[key]的值。
映射类型操作符
i)标准类型操作符
关系操作符,逻辑操作符,is, is not
ii)映射类型操作符
[], in, not in
用dict[key] = value, dict[key]来访问字典数据项,更新字典数据项
用key in dict 或 key not in dict来判断字典中是否有对应的key。
也可用字典的内建函数has_key()函数来表示in和not in
映射类型的内建函数
i)标准类型内建函数
type(), str()函数和cmp()函数。
对字典的比较不是很有用,也不常见(书里说的),因此不说了。我也懒得看这段。
ii)用于映射的内建函数
dict()
下面是在python解释器中用help(dict)后得到的有关dict()函数的东西。
| dict() -> new empty dictionary. # 返回空的字典
| dict(mapping) -> new dictionary initialized from a mapping object's
| (key, value) pairs. # 利用一个映射类型来返回字典
| dict(seq) -> new dictionary initialized as if via:
| d = {} # 利用序列来返回字典
| for k, v in seq:
| d[k] = v
| dict(**kwargs) -> new dictionary initialized with the name=value pairs
| in the keyword argument list. For example: dict(one=1, two=2)
# 利用name=value的参数列表来返回字典。
注意dict(mapping)函数,由于目前的映射类型就只有字典,因此这个函数总是根据一个字典来返回该字典的一个拷贝。该操作可以用dict.copy()函数来代替,而且copy()函数的速度更快,要注意的是它们都是浅拷贝。
len():返回字典中key-value对的个数。
hash(): 用一个对象作为参数,返回该对象的哈希值。如果该对象(如列表)不能hash,则该函数抛出TypeError错误。有着相同值得对象,有相同的哈希值
- >>> a = (1, 2, 3)
-
>>> b = tuple([1,2,3])
-
>>> a is b # a和b是不同的对象,但有着相同的值
-
False
-
>>> hash(a)
-
-378539185
-
>>> hash(b)
-
-378539185
-
>>> hash((1,2,[])) # 含有列表的元组不能hash
-
Traceback (most recent call last):
-
File "", line 1, in <module>
-
TypeError: unhashable type: 'list'
-
>>>
iii)字典的内建方法
dict.clear() : 删除字典中的所有元素
dict.copy() : 返回字典的一个副本,浅拷贝
dict.fromkeys(seq, val=None) : 创建并返回一个字典,seq中的元素为key值,val为默认的value值。
dict.get(key,default=None) : 返回字典中的dict[key]的值,若字典中没有key,则返回default的值,默认为None。这与直接调用dict[key]的区别在于,该函数不抛出异常。
dict.hash_key(key) : 字典中存在key就返回True,否则False。
dict.items() : 返回字典中(key,value)的列表,注意返回的是一个列表,列表中的每个元素都是一个(key,value)的元组。
dict.keys() : 返回字典的所有key的列表
dict.values() : 返回字典的所有value的列表
dict.iter*() : 包括dict.iteritems(), dict.iterkeys(),dict.itervalues(),与dict.items(),dict.keys(),dict.values()不同的是,iter*返回的迭代器,而不是列表。
dict.pop(key[,default]) : 返回dict[key]的值,并删除dict[key],若key键不存在,且没给定default,则抛出KeyError异常
dict.setdefault(key, default=None) : 即dict.get(key, default),而且如果key不在字典中,则插入字典dict[key]=value
dict.update(dict1) : 将dict1的key-value对插入字典dict。
可以将上面的函数简单分类,方便记忆
i)与字典创建有关:copy, fromkeys
ii)与字典遍历有关:items, keys, values; iteritems, iterkeys, itervalues
iii)与字典访问有关:get, setdefault
iv)与字典更新有关:pop,update,clear
v)其他: has_key
有关fromkeys()函数:
假设这样的一个问题:一个文件中有一堆单词,我想把有相同长度的单词弄一起,而且假设单词长度不会超过10,那我建立一个列表a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],然后用fromkeys建立一个字典,其中key值为1,2,...;values是一个列表,列表中要存储对应长度的单词。
那么我可能会这么做:
- >>> a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
-
>>> d = dict.fromkeys(a, [])
-
>>> d
-
{1: [], 2: [], 3: [], 4: [], 5: [], 6: [], 7: [], 8: [], 9: [], 10: []}
-
>>>
但这样是有错误的。
- >>> d[1].append('a')
-
>>> d
-
{1: ['a'], 2: ['a'], 3: ['a'], 4: ['a'], 5: ['a'], 6: ['a'], 7: ['a'], 8: ['a'],
-
9: ['a'], 10: ['a']}
-
>>>
所以这是个陷阱。可以如下完成这个任务
- >>> d = {}
-
>>> for i in a:
-
... d[i] = []
-
...
-
>>> d
-
{1: [], 2: [], 3: [], 4: [], 5: [], 6: [], 7: [], 8: [], 9: [], 10: []}
-
>>> d[1].append('a')
-
>>> d
-
{1: ['a'], 2: [], 3: [], 4: [], 5: [], 6: [], 7: [], 8: [], 9: [], 10: []}
-
>>>
有关iteritems, iterkeys, itervalues:
若字典d = {'a':1, 'b':0, 'c':1, 'd':0},要删除其中value为0的键,代码如下:
- >>> for i in d:
-
... if d[i] == 0:
-
... d.pop(i)
-
...
但不幸的是,这样是错误的。
- Traceback (most recent call last):
-
File "", line 1, in <module>
-
RuntimeError: dictionary changed size during iteration
-
>>> d
-
{'a': 1, 'c': 1, 'd': 0}
因此错误原因是:我们在迭代d的时候修改了d。对于iteritems, iterkeys, itervalues都会有这种问题。需要注意。
关于这个问题我是在这篇文章中看到的: 可以去看看,里面提到一些完成这个任务的方法。
本来是想把映射类型和集合类型方一起讲,但发现映射类型讲的内容挺多,所以还是分开。