Chinaunix首页 | 论坛 | 博客
  • 博客访问: 248206
  • 博文数量: 44
  • 博客积分: 1052
  • 博客等级: 少尉
  • 技术积分: 742
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-17 16:51
文章分类

全部博文(44)

文章存档

2013年(7)

2012年(14)

2011年(23)

分类: Python/Ruby

2011-08-22 20:24:46

字典是Python中唯一的映射类型。字典对象是可变的容器类型。
字典是用{}括起来的key,value对。字典中的数据是无序排列的,因此不能切片。

字典的创建
  1. >>> d = {}               # 创建空字典
  2. >>> d
  3. {}
  4. >>> d1 = {'name':'earth', 'port':80, 'age':12, 'age':23}  # 用key:value的方式创建字典
  5. >>> d1
  6. {'age': 23, 'name': 'earth', 'port': 80}   # 相同的key最后只能出现一个。
  7. >>> dict(([1, 'hi'],[2,'hello']))    # 用dict函数生成字典
  8. {1: 'hi', 2: 'hello'}
  9. >>> dict(x=1,y=2)                    # dict函数有多个重载,下面会介绍
  10. {'y': 2, 'x': 1}
  11. >>> dict.fromkeys(('x','y'),-1)      # 用dict的fromkeys函数生成字典, 这里-1为默认值
  12. {'y': -1, 'x': -1}
  13. >>> {}.fromkeys(('x','y'))           # 不指定默认值时,为None
  14. {'y': None, 'x': None}
  15. >>>
关于dict()函数和fromkeys()函数,后面会说。
关于字典的key:
i)一个key只会有一个对应值,即使你在初始化时指定多个值,但最终也只对应一个值。上面的字典d1就说明了这个问题
ii)key必须是可hash的。不可变的类型都是可hash的,如数字和字符串。也因此字典的key不能为列表和字典。如果元组的元素是:数字、字符串或只包含数字和字符串的元组,那这种元组也可以作为key。可见这里关键的还是可不可变。

字典的访问
  1. >>> d = {'name':'earth', 1:'first', ('temp','tuple'):'tuple'}
  2. >>> d['name']                    # 用dict[key]的方式来访问对应的value
  3. 'earth'
  4. >>> d[1]
  5. 'first'
  6. >>> d[('temp','tuple')]
  7. 'tuple'
  8. >>> for key in d.keys():         # keys()函数返回字典的key的列表
  9. ... print '[',key,',',d[key],']'
  10. ...
  11. [ 1 , first ]
  12. [ ('temp', 'tuple') , tuple ]
  13. [ name , earth ]
  14. >>> for key in d:                # 字典本身也可以作为一个迭代器来迭代
  15. ... print 'key=%s, value=%s' % (key, d[key])
  16. ...
  17. key=1, value=first
  18. key=('temp', 'tuple'), value=tuple
  19. key=name, value=earth
  20. >>> d[2]                         # 若访问字典中不存在的key,就会抛出KeyError异常
  21. Traceback (most recent call last):
  22.   File "", line 1, in <module>
  23. KeyError: 2
  24. >>>
可见字典的访问就是用dict[key]的方式访问单个元素,用dict.keys()或dict本身来循环访问字典中所有key。

字典的更新
更新包括:字典中添加(key,value)对、修改已存在的数据项、删除存在的数据项
  1. >>> d = {'name':'earth', 1:'first', ('temp','tuple'):'tuple'}
  2. >>> d['ans'] = 42           # 用d[key]=value的方式直接插入数据项
  3. >>> d
  4. {1: 'first', ('temp', 'tuple'): 'tuple', 'name': 'earth', 'ans': 42}
  5. >>> d['name'] = 'mars'      # 用d[key]=value的方式直接改变数据项
  6. >>> d
  7. {1: 'first', ('temp', 'tuple'): 'tuple', 'name': 'mars', 'ans': 42}
  8. >>> del d[('temp','tuple')] # 用del d[key]的方式删除数据项
  9. >>> d
  10. {1: 'first', 'name': 'mars', 'ans': 42}
  11. >>> a = d.pop('name')       # 用pop(key)函数,返回d[key],并删除d[key]
  12. >>> a
  13. 'mars'
  14. >>> d
  15. {1: 'first', 'ans': 42}
  16. >>> d.clear()               # clear()函数删除所有数据项
  17. >>> d
  18. {}
  19. >>> del d                   # 删除字典本身
  20. >>> d
  21. Traceback (most recent call last):
  22.   File "", line 1, in <module>
  23. NameError: name 'd' is not defined
  24. >>>
因此用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错误。有着相同值得对象,有相同的哈希值
  1. >>> a = (1, 2, 3)
  2. >>> b = tuple([1,2,3])
  3. >>> a is b          # a和b是不同的对象,但有着相同的值
  4. False
  5. >>> hash(a)
  6. -378539185
  7. >>> hash(b)
  8. -378539185
  9. >>> hash((1,2,[]))   # 含有列表的元组不能hash
  10. Traceback (most recent call last):
  11.   File "", line 1, in <module>
  12. TypeError: unhashable type: 'list'
  13. >>>
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是一个列表,列表中要存储对应长度的单词。
那么我可能会这么做:
  1. >>> a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  2. >>> d = dict.fromkeys(a, [])
  3. >>> d
  4. {1: [], 2: [], 3: [], 4: [], 5: [], 6: [], 7: [], 8: [], 9: [], 10: []}
  5. >>>
但这样是有错误的。
  1. >>> d[1].append('a')
  2. >>> d
  3. {1: ['a'], 2: ['a'], 3: ['a'], 4: ['a'], 5: ['a'], 6: ['a'], 7: ['a'], 8: ['a'],
  4.  9: ['a'], 10: ['a']}
  5. >>>
所以这是个陷阱。可以如下完成这个任务
  1. >>> d = {}
  2. >>> for i in a:
  3. ...     d[i] = []
  4. ...
  5. >>> d
  6. {1: [], 2: [], 3: [], 4: [], 5: [], 6: [], 7: [], 8: [], 9: [], 10: []}
  7. >>> d[1].append('a')
  8. >>> d
  9. {1: ['a'], 2: [], 3: [], 4: [], 5: [], 6: [], 7: [], 8: [], 9: [], 10: []}
  10. >>>
有关iteritems, iterkeys, itervalues:
若字典d = {'a':1, 'b':0, 'c':1, 'd':0},要删除其中value为0的键,代码如下:
  1. >>> for i in d:
  2. ... if d[i] == 0:
  3. ...     d.pop(i)
  4. ...
但不幸的是,这样是错误的。
  1. Traceback (most recent call last):
  2.   File "", line 1, in <module>
  3. RuntimeError: dictionary changed size during iteration
  4. >>> d
  5. {'a': 1, 'c': 1, 'd': 0}
因此错误原因是:我们在迭代d的时候修改了d。对于iteritems, iterkeys, itervalues都会有这种问题。需要注意。
关于这个问题我是在这篇文章中看到的:   可以去看看,里面提到一些完成这个任务的方法。


本来是想把映射类型和集合类型方一起讲,但发现映射类型讲的内容挺多,所以还是分开。
阅读(1410) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~