美文网首页
13 Python字典

13 Python字典

作者: 泷汰泱 | 来源:发表于2019-09-26 10:51 被阅读0次

    字典是Python中唯一内建的映射类型,字典指定值并没有特殊顺序,都存储在一个特殊的键(Key)里,键可以是数字、字符串或元组。
    字典是另一种可变容器模型,可存储任意类型对象。

    字典的使用

    字典这个数据结构的功能就跟它的名字一样,可以像《汉语字典》一样使用。在使用汉语字典时,我们可以从头到尾一页一页查找某个字,也可以通过拼音索引或笔画索引快速找到某个字,在汉语字典中找拼音索引和笔画索引非常轻松简单。
    在Python中对字典进行了构造,让我们可以轻松查到某个特定的键(类似拼音或笔画索引),从而通过键找到对应的值(类似具体某个字)。
    假如需要创建一个可以存储学生姓名和学号的小型数据库,应该怎么做呢?我们尝试使用之前学习过的列表实现,例如:

    >>> students=['小萌','小智','小强','小张','小李']
    >>> numbers=['1001','1002','1003','1004','1005']
    >>> print('小智的学号是:',numbers[students.index('小智')])
    小智的学号是: 1002
    

    输出结果是我们想要的,但是当数据量比较大时,显然不适用。数据量比较大时,意味着要对学生姓名列表创建一个有同样多元素的学号列表,一旦列表发生变更,就要将学号列表和学生姓名列表进行逐步比对,以进行相应变更。
    我们想要的真正效果是像使用index方法一样,index返回的是索引位置,我们希望直接返回索引位置上的值,比如:

    >>> print('小智的学号是:',numbers['小智'])
    小智的学号是: 1002
    

    这种方式可以实现,如果numbers是字典,就可以这么操作并得到结果。

    创建和使用字典

    字典的创建格式如下:

    >>> d = {key1 : value1, key2 : value2 }
    

    字典由多个键及其对应的值构成的对组成(把键/值对称为项)。字典的每个键/值(key/value)对用冒号(:)分割,每个项之间用逗号(,)分割,整个字典包括在花括号({})中。空字典(不包括任何项)由两个大括号组成,如{}。
    键必须是唯一的,但值不必。值可以取任何数据类型,键必须是不可变的,如字符串、数字或元组。
    下面是一个简单的字典示例:

    >>> dict = {'小萌': '1001', '小智': '1002', '小强': '1003'}
    也可以为如下形式:
    >>> dict1 = { 'abc': 456 }
    >>> dict2 = { 'abc': 123, 98.6: 37 }
    

    1 dict函数

    可以用dict函数,通过其他映射(如其他字典)或键/值序列对建立字典,例如:

    >>> student=[('name','小萌'),('number','1001')]
    >>> detail=dict(student)
    >>> print('学生详细信息:',detail)
    学生详细信息: {'name': '小萌', 'number': '1001'}
    >>> print('学生姓名:',detail['name'])
    学生姓名: 小萌
    >>> print('学生学号:',detail['number'])
    学生学号: 1001
    

    由输出结果看到,dict函数可以将序列转换为字典。字典的操作很简单,在5.1节期望的功能已经实现了。
    dict函数可以通过关键字参数创建字典,例如:

    >>> detail=dict(name='小智',number='1002')
    >>> print('学生详细信息:',detail)
    学生详细信息: {'name': '小智', 'number': '1002'}
    

    由输出结果看到,通过关键字参数创建了字典。
    通过关键字创建字典功能是dict函数非常有用的一个功能,可以多加运用。

    2 字典的基本操作

    字典的基本操作在很多方面与序列(sequence)类似,支持修改、删除等操作。下面进行具体的讲解。
    1. 修改字典
    向字典添加新内容的方法是增加新键/值对,修改或删除已有键/值对,例如:

    >>> student={'小萌':'1001','小智':'1002','小强':'1003'}
    >>> student['小强']='1005' #更新小强的学号
    >>> print('小强的学号是:%(小强)s' % student)
    小强的学号是:1005
    >>> student['小张']='1006' #添加一个学生
    >>> print('小张的学号是:%(小张)s' % student)
    小张的学号是:1006
    

    由输出结果看到,修改和添加均操作成功。
    2. 删除字典元素
    此处的删除指的是显式删除,显式删除一个字典用del命令,例如:

    >>> student={'小强': '1005', '小萌': '1001', '小智': '1002', '小张': '1006'}
    >>> print('删除前:',student)
    删除前: {'小强': '1005', '小萌': '1001', '小智': '1002', '小张': '1006'}
    >>> del student['小张'] #删除键“小张”
    >>> print('删除后:',student)
    删除后: {'小强': '1005', '小萌': '1001', '小智': '1002'}
    

    由输出结果看到对应键/值被正确删除了。
    除了删除键,还可以删除整个字典,例如:

    >>> student={'小强': '1005', '小萌': '1001', '小智': '1002', '小张': '1006'}
    >>> print('删除前:',student)
    删除前: {'小强': '1005', '小萌': '1001', '小智': '1002', '小张': '1006'}
    >>> del student #删除字典
    >>> print('删除后:',student)
    Traceback (most recent call last):
      File "<pyshell#70>", line 1, in <module>
        print('删除后:',student)
    NameError: name 'student' is not defined
    

    由输出结果看到,删除字典后就不能对字典进行访问了,因为执行del操作后字典就不存在了,因而会报变量没有定义的错误。
    3. 字典键的特性
    字典值可以没有限制地取任何Python对象,既可以是标准对象,也可以是用户定义的对象,但键不行。
    需要记住以下两点:
    (1)不允许同一个键出现两次。创建时如果同一个键被赋值两次,后面的值会被记住,例如:

    >>> student={'小萌': '1001', '小智': '1002', '小萌': '1005'}
    >>> print('学生信息:',student)
    学生信息: {'小萌': '1005', '小智': '1002'}
    

    由输出结果看到,一个键被赋值两次,后面的值会被记住。
    (2)键必须不可变,可以用数字、字符串或元组充当,不能用列表,例如:

    >>> field={['name']:'小萌','number':'1001'}
    Traceback (most recent call last):
      File "<pyshell#80>", line 1, in <module>
        field={['name']:'小萌','number':'1001'}
    TypeError: unhashable type: 'list'
    

    由输出结果看到,不能用列表做键,会提示类型错误。
    4. len函数
    len(dict)函数用于计算字典元素的个数,即键的总数,例如:

    >>> student={'小萌': '1001', '小智': '1002', '小强': '1005','小张': '1006'}
    >>> print('字典元素个数为:%d 个' % len(student))
    字典元素个数为:4 个
    

    输出结果得到字典元素的个数为4。
    5. type 函数
    type(variable)函数返回输入的变量类型,如果输入变量是字典就返回字典类型,例如:

    >>> student={'小萌': '1001', '小智': '1002', '小强': '1005','小张': '1006'}
    >>> print('字典的类型为:',type(student))
    字典的类型为: <class 'dict'>
    

    输出结果为字典(dict)类型。

    3 字典的格式化字符串

    在第4章我们已经见过如何使用字符串格式化功能格式化元组中的所有值。如果使用字典(只以字符串作为键)而不是元组做这项工作,会使字符串格式化更有趣一些,例如:

    >>> student={'小萌':'1001','小智':'1002','小强':'1003'}
    >>> print('小强的学号是:%(小强)s' % student)
    小强的学号是:1003
    

    由操作结果看到,字典的格式化方式是在每个转换说明符中的%字符后加上用圆括号括起来的键,再跟上其他说明元素。
    字典的格式化除了增加字符串键外,转换说明符还像以前一样工作。以这种方式使用字典时,只要所有给出的键都能在字典中找到,就可以获得任意数量的转换说明符。

    4 字典和列表的区别

    例如,以一个名字查找对应的学号。
    如果用list实现,就要先在名字列表中找到对应的名字,再从学号列表取出对应的学号,list越长耗时越长。如果用dict实现,只需要一个名字和学号的对照表,就可以直接根据名字查找学号,无论这个表有多大,查找速度都不会变慢。
    为什么dict查找速度这么快?
    因为dict的实现原理和查字典一样。假设字典包含10000个汉字,我们要查某一个字,一种方法是把字典从第一页往后翻,直到找到我们想要的字为止,这种方法是在list中查找元素,list越大查找越慢。另一种方法是在字典的索引表里(如部首表)查这个字对应的页码,然后直接翻到该页找到这个字。无论找哪个字,这种查找速度都非常快,不会随着字典大小的增加而变慢。
    dict就是第二种实现方法,给定一个名字,比如我们要查找5.2.3小节示例中“小萌”的学号,在dict内部就可以直接计算出“小萌”存放学号的“页码”,也就是1001存放的内存地址,直接取出来即可,所以速度非常快。
    综上所述,list和dict各有以下几个特点:

    dict的特点是:

    (1)查找和插入的速度极快,不会随着key的增加而变慢。
    (2)需要占用大量内存,内存浪费多。

    list的特点是:

    (1)查找和插入时间随着元素的增加而增加。
    (2)占用空间小,浪费内存很少。
    所以,dict是使用空间换取时间。
    dict可以用在很多需要高速查找的地方,在Python代码中几乎无处不在,正确使用dict非常重要,需要牢记dict的键必须是不可变对象。
    注意:dict内部存放的顺序和键放入的顺序没有关系。

    字典方法

    像其他内建类型一样,字典也有方法,这些方法非常有用,不过可能不像使用列表或字符串一样频繁使用。学习本节时可以先简单浏览了解一下有哪些方法可以使用,然后在需要时回过头来查看特定方法的具体用法。
    1 clear()方法
    clear()方法用于删除字典内的所有项。
    clear()方法的语法如下:

    dict.clear()

    此语法中dict代表指定字典,该方法不需要参数。该函数是一个原地操作(类似于list.sort)函数,没有任何返回值(返回值为None)。
    该方法使用示例如下:

    >>> student={'小萌': '1001', '小智': '1002', '小强': '1005','小张': '1006'}
    >>> print('字典元素个数为:%d 个' % len(student))
    字典元素个数为:4 个
    >>> student.clear()
    >>> print('字典删除后元素个数为:%d 个' % len(student))
    字典删除后元素个数为:0 个
    

    由输出结果可知,字典调用clear方法后整个字典内所有项都被删除。
    下面看两个示例。
    示例1:

    >>> x={}
    >>> y=x
    >>> x['key']='value'
    >>> y
    {'key': 'value'}
    >>> x={}
    >>> y
    {'key': 'value'}
    

    示例2:

    >>> x={}
    >>> y=x
    >>> x['key']='value'
    >>> y
    {'key': 'value'}
    >>> x.clear()
    >>> y
    {}
    

    两个示例中,x和y最初对应同一个字典。示例1中,通过将x关联到一个新的空字典对它重新赋值,这对y没有任何影响,还关联到原先的字典。若想清空原始字典中所有元素,则必须使用clear方法,使用clear后,y的值也被清空了。
    2 copy()方法
    copy()方法返回一个具有相同键/值对的新字典。这个方法是浅复制(shallow copy),因为值本身是相同的,而不是副本。
    copy()方法的语法如下:

    dict.copy()

    此语法中dict代表指定字典,该方法不需要参数。返回结果为一个字典的浅复制。该方法使用示例如下:

    >>> student={'小萌': '1001', '小智': '1002', '小强': '1005','小张': '1006'}
    >>> st=student.copy()
    >>> print('复制后得到的st为:',st)
    复制后得到的st为: {'小强': '1005', '小萌': '1001', '小智': '1002', '小张': '1006'}
    

    由输出结果看到,使用copy方法可以将字典复制给另一个变量。
    我们可以通过下面的示例了解什么是浅复制

    >>> student={'小智': '1002', 'info':['小张','1006','man']}
    >>> st=student.copy()
    >>> st['小智']='1005'
    >>> print('更改copy 后的st为:',st)
    更改copy 后的st为: {'info': ['小张', '1006', 'man'], '小智': '1005'}
    >>> print('原字符串为::',student)
    原字符串为:: {'info': ['小张', '1006', 'man'], '小智': '1002'}
    >>> st['info'].remove('man')
    >>> print('删除后st为:',st)
    删除后st为: {'info': ['小张', '1006'], '小智': '1005'}
    >>> print('删除后student为:',student)
    删除后student 为: {'info': ['小张', '1006'], '小智': '1002'}
    

    由输出结果看到,替换副本的值时原始字典不受影响。如果修改了某个值(原地修改,不是替换),原始字典就会改变,因为同样的值也在原字典中。以这种方式进行复制就是浅复制,而使用深复制(deep copy)可以避免该问题,此处不做讲解,有兴趣的读者可以自己查找相关资料。
    3 fromkeys()方法
    fromkeys()方法用于创建一个新字典,以序列seq中的元素做字典的键,value为字典所有键对应的初始值。
    fromkeys()方法的语法如下:

    dict.fromkeys(seq[, value]))

    此语法中dict代表指定字典;seq代表字典键值列表;value代表可选参数,设置键序列(seq)的值。该方法返回结果为列表。
    该方法使用示例如下:

    >>> seq = ('name', 'age', 'sex')
    >>> info = dict.fromkeys(seq)
    >>> print ("新的字典为 : %s" %   info)
    新的字典为 : {'name': None, 'sex': None, 'age': None}
    >>> info = dict.fromkeys(seq, 10)
    >>> print ("新的字典为 : %s" %   info)
    新的字典为 : {'name': 10, 'sex': 10, 'age': 10}
    

    由输出结果看出,fromkeys方法使用给定的键建立新字典,每个键默认对应的值为None。
    4 get()方法
    get()方法返回指定键的值,如果值不在字典中,就返回默认值。
    get()方法的语法如下:

    dict.get(key, default=None)

    此语法中dict代表指定字典,key代表字典中要查找的键,default代表指定键的值不存在时返回默认值。该方法返回结果为指定键的值,如果值不在字典中,就返回默认值None。
    该方法使用示例如下:

    >>> student={'小萌': '1001', '小智': '1002'}
    >>> print ('小萌的学号为: %s' %  student.get('小萌'))
    小萌的学号为: 1001
    

    由输出结果看到,get方法使用起来比较简单。再看如下示例:

    >>> st={}
    >>> print(st['name'])
    Traceback (most recent call last):
      File "<pyshell#166>", line 1, in <module>
        print(st['name'])
    KeyError: 'name'
    >>> print(st.get('name'))
    None
    >>> print('name 的值为:%s' % st.get('name'))
    name 的值为:None
    

    由输出结果看到,其他方法试图访问字典中不存在的项时会出错,而使用get方法就不会。使用get方法访问一个不存在的键时,返回None。这里可以自定义默认值,用于替换None,例如:

    >>> st={}
    >>> print('name 的值为:%s' % st.get('name','未指定'))
    name 的值为:未指定
    

    由输出结果看到,输出结果中用“未指定”替代了None。
    5 key in dict方法
    Python字典in操作符用于判断键是否存在于字典中,如果键在字典dict中就返回true,否则返回false。
    该方法的语法如下:

    key in dict

    此语法中dict代表指定字典,key代表要在字典中查找的键。如果键在字典里就返回true,否则返回false。
    该方法使用示例如下:

    >>> student={'小萌': '1001', '小智': '1002'}
    >>> print('小萌在student字典中:%s'%('小萌' in student))
    小萌在student 字典中:True
    >>> print('小强在student字典中:%s'%('小强' in student))
    小强在student 字典中:False
    

    由输出结果看到,已返回对应的True或False。
    该方法是Python 3中的方法。在Python 2中有一个有相同功能的方法——has_key方法,has_key方法的使用方式和in不同。
    6 items()方法
    items()方法以列表返回可遍历的(键,值)元组数组。
    items()方法的语法如下:

    dict.items()

    此语法中dict代表指定字典,该方法不需要参数。返回结果为可遍历的(键/值)元组数组。
    该方法使用示例如下:

    >>> student={'小萌': '1001', '小智': '1002'}
    >>> print('调用items方法的结果:%s'% student.items())
    调用items 方法的结果:dict_items([('小萌', '1001'), ('小智', '1002')])
    

    由输出结果看到,返回结果为一个元组数组。
    在Python 2中提供了一个iteritems方法,该方法和items方法的作用大致相同,但是iteritems方法返回的是一个迭代器对象,而不是列表。在Python 3中没有iteritems方法。
    7 keys()方法
    keys()方法以列表返回一个字典所有键。
    keys()方法的语法如下:

    dict.keys()

    此语法中dict代表指定字典,该方法不需要参数。返回结果为一个字典所有键。
    该方法使用示例如下:

    >>> student={'小萌': '1001', '小智': '1002'}
    >>> print('字典student所有键为:%s'% student.keys())
    字典student 所有键为:dict_keys(['小萌', '小智'])
    

    由输出结果看到,返回的是一个元组数组,数组中包含字典所有键。
    8 setdefault()方法
    setdefault()方法和get()方法类似,用于获得与给定键相关联的值。如果键不存在于字典中,就会添加键并将值设为默认值。
    setdefault()方法的语法如下:

    dict.setdefault(key, default=None)

    此语法中dict代表指定字典,key代表查找的键值,default代表键不存在时设置的默认键值。该方法没有任何返回值。
    该方法使用示例如下:

    >>> student={'小萌': '1001', '小智': '1002'}
    >>> print('小强的键值为:%s'% student.setdefault('小强'))
    小强的键值为:None
    >>> print('小智的键值为:%s'% student.setdefault('小智'))
    小智的键值为:1002
    >>> print('student 字典新值为:%s'% student)
    student 字典新值为:{'小强': None, '小萌': '1001', '小智': '1002'}
    

    由输出结果看到,当键不存在时,setdefault方法返回默认值并更新字典;如果键存在,就返回与其对应的值,不改变字典。和get一样,默认值可以选择,如果不设定就使用None,如果设定就使用设定的值,例如:

    >>> student={'小萌': '1001', '小智': '1002'}
    >>> print('小强的键值为:%s'% student.setdefault('小强'))
    小强的键值为:None
    >>> print('小zhang 的键值为:%s'% student.setdefault('小zhang','1006'))
    小zhang 的键值为:1006
    

    由输出结果看到,小强没有设置值,使用的是默认值,输出键值为None;小zhang设置的默认值是1006,输出键值为1006。
    9 update()方法
    update()方法用于把字典dict2的键/值对更新到dict里。
    update()方法的语法如下:

    dict.update(dict2)

    此语法中dict代表指定字典,dict2代表添加到指定字典dict里的字典。该方法没有任何返回值。
    该方法使用示例如下:

    >>> student={'小萌': '1001', '小智': '1002'}
    >>> student2={'小李':'1003'}
    >>> print('原student 字典为:%s'% student)
    原student字典为:{'小萌': '1001', '小智': '1002'}
    >>> student.update(student2)
    >>> print('新student 字典为:%s'% student)
    新student字典为:{'小李': '1003', '小萌': '1001', '小智': '1002'}
    >>> student3={'小李':'1005'}
    >>> student.update(student3) #对相同项覆盖
    >>> print('新student 字典为:%s'% student)
    新student字典为:{'小李': '1005', '小萌': '1001', '小智': '1002'}
    

    由输出结果看到,提供的字典中的项被添加到旧字典中,如果有相同的键就会覆盖。
    10 values()方法
    values()方法以列表形式返回字典中所有值。与返回键的列表不同,返回的列表中可以包含重复的元素。
    values()方法的语法如下:

    dict.values()

    此语法中dict代表指定字典,该方法不需要参数。返回结果为字典中的所有值。
    该方法使用示例如下:

    >>> student={'小萌': '1001', '小智': '1002','小李':'1001'}
    >>> print('student 字典所有值为:%s'% list(student.values()))
    student 字典所有值为:['1001', '1001', '1002']
    

    由输出结果看到,返回的列表中包含重复的元素。

    调试

    下面我们通过示例进行介绍,这里通过设置一些错误让读者认识在编写代码过程中的常见问题,以帮助读者熟悉和解决实际遇到的问题。
    (1)使用列表根据姓名查找学号,学号使用字符串表示,如果更改为使用数字表示会如何?例如:

    >>> students=['小萌','小智','小强','小张','小李']
    >>> numbers=[1001,1002,1003,1004,1005]
    >>> print('小智的学号是:',numbers[students.index('小智')])
    小智的学号是: 1002
    

    输出结果和使用字符串表示的输出结果没有什么不同。不过这里数字都是以1开头,若把1更改为0,我们试试:

    >>> students=['小萌','小智','小强','小张','小李']
    >>> numbers=[0001,0002,0003,0004,0005]
    SyntaxError: invalid token
    

    可以看出,numbers的编译不让通过,告诉我们这是一个无效标记。这就是不使用数字而使用字符串的原因,使用数字碰到以0开头的数字就会出现问题。
    (2)尝试从字典中输出一个字符宽度为10的元素?例如:

    >>> student={'小萌':'1001','小智':'1002','小强':'1003'}
    >>> print('小萌的学号是:%(小萌)10s' % student) #字符宽度为10
    小萌的学号是:        1001
    

    尝试把10s变换为10d、10f、-10s、+10s,看看输出结果是怎样的。

    相关文章

      网友评论

          本文标题:13 Python字典

          本文链接:https://www.haomeiwen.com/subject/zbfhyctx.html