1. 结构严谨、内容翔实,2. 以项目为驱动,以模板形式介绍项目开发过程,3. 理论联系实际项目,既适合初学者夯实基础,又能帮助Python程序员提升技能。4. 既可作为各类大中专学校的教材,也可以作为程序员自学用书。
第5章映射和集合类型本章学习目标 掌握字典的创建、访问、更新 熟悉字典的常用内置函数 掌握集合的创建、访问、更新 熟悉集合的常用内置函数
在前面的章节中已经介绍了整型、浮点型、字符串、列表等数据类型。本章将介绍另外两种数据类型: 映射(字典)和集合类型。5.1映射类型——字典字典是Python语言中唯一的映射类型。这种映射类型由键(key)和值(value)组成(统称为“键值对”),一个键只能对应一个值,但多个键可以对应相同的值。字典对象是可变的数据类型,可以存储任意个键值对。字典中的值没有特定顺序,每个值都对应一个唯一的键,字典也被称作关联数组或哈希表。字典类型和序列类型的区别在于其存储和访问数据方式的不同。序列类型只用整型作为其索引,或者说只用整型作为其键。映射类型则可以用其他对象类型作为键。并且映射类型的键和其指向的值有一定的关联性,而序列类型则没有。正是由于映射类型的键可以“映射”到值,所以才称其为映射类型。注意: 字典的键必须是可哈希的对象,如字符串、整型、元组(元素不包含可变数据类型)都是可哈希的对象,都可以作为字典的键,而列表、字典是不可哈希的对象,所以不能用作字典的键。可以简单地把直接或间接不包含可变数据类型的对象看作可哈希的对象,当然,最妥当的方法还是通过hash()函数来判断某个对象是否是可哈希的对象。5.1.1创建字典字典由一系列的“键值对”组成,可以通过使用花括号,并把花括号里的每一个键值对采用逗号进行分隔,键值对中间用冒号隔开的方式来创建一个字典。创建字典的一般格式如下: dictionary_name={key1:value1,key2:value2,...,keyN:valueN}其中,key1、key2、keyN等表示字典的键,value1、value2、valueN表示字典的键对应的值。此外,还可以通过内建函数dict()方法和fromkeys()方法创建一个字典。dict()函数可以接收以(key,value)形式的列表或元组。使用fromkeys()函数可以创建一个“默认”字典,字典中键对应的值都相同,如果没有指定值,默认为None。# 例51创建字典# 1. 通过普通方式来创建字典# 字典的键为数字,值为字符串>>>student1_dict={1001:"xiaowang",1002:"xiaoli",1003:"xiaochen"}# 字典的键为字符串,值也为字符串>>>student2_dict={"1001":"xiaowang","1002":"xiaoli","1003":"xiaochen"}>>>student1_dict{1001:"xiaowang",1002:"xiaoli",1003:"xiaochen"}>>>student2_dict{'1003': 'xiaochen', '1002': 'xiaoli', '1001': 'xiaowang'}
# 2. 通过内建函数dict()来创建字典# 以(key,value)形式的列表>>>student3_dict=dict(\[(1001,"xiaowang"),(1002,"xiaoli"),(1003,"xiaochen")\])# 以(key,value)形式的元组>>>student4_dict=dict(((1001,"xiaowang"),(1002,"xiaoli"),(1003,"xiaochen")))>>>student3_dict{1001:"xiaowang",1002:"xiaoli",1003:"xiaochen"}>>>student4_dict{1001:"xiaowang",1002:"xiaoli",1003:"xiaochen"}
# 3. 通过内建函数fromkeys()来创建字典# 指定value值为"person">>>student5_dict={}.fromkeys((1001,1002,1003),"person")# 不指定value值>>>student6_dict={}.fromkeys((1001,1002,1003))>>>student5_dict{1001:"person",1002:"person",1003:"person"}>>>student6_dict{1001:None,1002:None,1003:None}[1]Python程序设计教程第5章映射和集合类型[3][3]这个例子,先通过普通的方式创建了一个含有三个键值对的字典“student1_dict”。键为学生编号,类型为整型,值为编号对应的学生。接着又创建了字典“student2_dict”,该字典的编号类型为字符串,输出时,可以发现输出的结果和所创建时给出的键值对顺序不一致。这是因为创建时给出的键值对顺序并不是字典的实际存储顺序,字典是根据每个键值对的键的hashcode值进行排序存储的。然后通过内建函数dict(),分别以列表和元组的参数形式创建字典,最后再通过fromkeys()函数创建两个字典。可以看到,当指定value为“person”时,其键值对中的值都是“person”,当没指定value时,其键值对中的值都使用默认值“None”。5.1.2访问字典访问字典中键值对的值可以通过方括号并指定相应的键的形式访问。需要注意的是,当指定一个字典中不存在的键时就会抛KeyError异常。遍历一个字典可以有以下几种方式: (1) 通过指定键的方式遍历字典。在Python 2.2以前,需要使用keys()函数获取字典的所有键。而在Python 2.2以后,可以直接遍历字典这个迭代器对象,每次返回的是字典的键,因此,可以通过dictionary_name\[key\]的方式访问对应的值,从而可以遍历字典中所有的键值对。(2) 通过内建函数items()遍历字典。该函数返回的是一个由键值对组成的元组的列表。因此,可以遍历这个列表,从而遍历字典中所有的键值对。(3) 通过内建函数iteritems()遍历字典。该函数返回的是键值对的迭代器。因此,可以直接得到这个键值对,从而遍历字典中所有的键值对。#coding:utf-8# 例52遍历字典# 定义含有三个键值对的字典student_dict={1001:"xiaowang",1002:"xiaoli",1003:"xiaochen"}# 1.1. 通过指定键的方式遍历字典(Python 2.2版本之前) print "循环遍历student_dict.keys():",student_dict.keys()for key in student_dict.keys():print 'student_dict\[%s\]=' % key,student_dict\[key\]
# 1.2. 通过指定键的方式遍历字典(Python 2.2版本之后)print "循环遍历student_dict:",student_dictfor key in student_dict:print 'student_dict\[%s\]=' % key,student_dict\[key\]
# 2. 通过内建函数items()遍历字典print "循环遍历student_dict.items():",student_dict.items()for (key,value) in student_dict.items():print 'student_dict\[%s\]=' % key,value
# 3. 通过内建函数iteritems()遍历字典print "循环遍历student_dict.iteritems():",student_dict.iteritems()for (key,value) in student_dict.iteritems():print 'student_dict\[%s\]=' % key,value程序的运行结果如下: 循环遍历student_dict.keys(): \[1001, 1002, 1003\]student_dict\[1001\]=xiaowangstudent_dict\[1002\]=xiaolistudent_dict\[1003\]=xiaochen循环遍历student_dict: {1001: 'xiaowang', 1002: 'xiaoli', 1003: 'xiaochen'}student_dict\[1001\]=xiaowangstudent_dict\[1002\]=xiaolistudent_dict\[1003\]=xiaochen循环遍历student_dict.items(): \[(1001, 'xiaowang'), (1002, 'xiaoli'), (1003, 'xiaochen')\]student_dict\[1001\]=xiaowangstudent_dict\[1002\]=xiaolistudent_dict\[1003\]=xiaochen循环遍历student_dict.iteritems():student_dict\[1001\]=xiaowangstudent_dict\[1002\]=xiaolistudent_dict\[1003\]=xiaochen这个程序首先定义了含有三个键值对(学生编号和对应的学生)的字典,然后三种方式遍历整个字典。第一种是通过指定键的方式遍历字典,这种方式又分两种情况: 在Python版本2.2以前,可以通过key()函数获得字典的所有键组成的列表。如程序中输出student_dict.keys()就输出了\[1001, 1002, 1003\];另一种情况是在Python 2.2版本以后,可以直接遍历字典对象,每次返回的是字典中的键。因此,这两种情况都可以通过student_dict\[key\]的方式获取key键对应的值,从而遍历这个字典。第二种是通过内建函数items()遍历字典。这个函数返回的是一个由键值对组成的元组的列表,如输出student_dict.keys()就输出了\[(1001, 'xiaowang'), (1002, 'xiaoli'), (1003, 'xiaochen')\]。因此,遍历这个列表就相当于遍历了字典。第三种是通过内建函数iteritems()遍历字典,这个函数返回的是一个键值对的迭代器,如输出student_dict.keys()就输出了。因此,遍历这个列表就相当于遍历了字典。5.1.3更新字典字典是可变数据类型,即字典的长度和元素都是可以改变的。下面将介绍更新字典的方式: 添加元素、修改元素和删除元素。说明: 本节讲的元素指定是键值对。1. 添加元素向字典添加一个元素可以通过赋值语句实现,该赋值语句的写法如下: dictionary_name\[key\]=value如果key在字典dictionary_name中不存在,则直接将元素(key,value)添加到字典中;如果key已存在,则value会覆盖原来字典中key对应的值,从而修改了字典中key对应的值(这种方式实现了修改元素的目的)。这种情况也相当于把元素(key,value)添加到字典中,但同时也删除了原来字典中含key的元素,字典的元素个数没有增加。#coding:utf-8# 例53使用赋值语句向字典添加一个元素# 定义一个含有三个元素(学生编号:学生)的字典student_dict={1001:"xiaowang",1002:"xiaoli",1003:"xiaochen"}# 使用len()函数获取student_dict字典中初始的个数,str()将整型转为字符串类型print '目前有' str(len(student_dict)) '个学生'print '刚来了一个学生"xiaozhang",给他分配的学生编号为1004'# 使用赋值语句向student_dict字典添加一个(1004,"xiaozhang")的元素student_dict\[1004\]="xiaozhang"# 再次输出此时student_dict字典的长度print '现在有' str(len(student_dict)) '个学生,他们分别是:'# 使用for循环遍历这个student_dict字典,分别输出这些元素for key in student_dict:print 'student_dict\[%s\]=' % key,student_dict\[key\]print '又来了一个学生"xiaoshui",给该学生分配一个该班里(字典)已用过的学生编号1004'# 使用赋值语句向student_dict字典添加一个(1004,"xiaoshui")的元素student_dict\[1004\]="xiaoshui"# 再次输出此时student_dict字典的长度print '现在有' str(len(student_dict)) '个学生,他们分别是:'# 使用for循环遍历这个student_dict字典,分别输出这些元素for key in student_dict:print 'student_dict\[%s\]=' % key,student_dict\[key\]程序运行结果如下: 目前有三个学生刚来了一个学生"xiaozhang",给他分配的学生编号为1004现在有4个学生,他们分别是:student_dict\[1001\]=xiaowangstudent_dict\[1002\]=xiaolistudent_dict\[1003\]=xiaochenstudent_dict\[1004\]=xiaozhang又来了一个学生"xiaoshui",给该学生分配一个该班里(字典)已用过的学生编号1004现在有4个学生,他们分别是:student_dict\[1001\]=xiaowangstudent_dict\[1002\]=xiaolistudent_dict\[1003\]=xiaochenstudent_dict\[1004\]=xiaoshui从程序运行结果可以看到,第一次使用赋值语句向字典添加元素(1004: "xiaozhang")后,遍历此时的字典,可以看到元素(1004: "xiaozhang")已被添加到字典中。第二次又使用赋值语句向字典添加元素(1004: "xiaoshui")后,遍历此时的字典,可以看到原来的元素(1004: "xiaozhang")已被新元素(1004: "xiaoshui")替换。或者说字典中键为"1004"对应的value值已被修改成"xiaoshui"。字典的元素个数没有增加。这是因为添加的元素的键在字典中已存在。此外,向字典中添加一个元素也可以通过setdefault()内建函数实现。该函数的声明如下: dictionary_name.setdefault(key\[,default_value\])其中,dictionary_name为字典名,参数key表示字典的键,参数default_value表示添加的字典元素默认的值。该参数为可选参数。如果不指定该参数的值,默认为None。如果要添加的参数key在字典中已存在,那么该函数将返回原有的值。否则这个元素将被添加到字典中,并返回所添加元素的value值。下面通过一个例子来说明如何使用setdefault()函数向字典添加一个元素。#coding:utf-8# 例54使用setdefault()函数向字典添加一个元素# 定义一个含有三个元素(学生编号:学生)的字典student_dict={1001:"xiaowang",1002:"xiaoli",1003:"xiaochen"}# 使用len()函数获取student_dict字典中初始的个数,str()将整型转为字符串类型print '目前有' str(len(student_dict)) '个学生'print '刚来了一个学生"xiaozhang",给他分配的学生编号为1004'# 使用setdefault()函数向student_dict字典添加一个(1004,"xiaozhang")的元素,并输# 出该函数的返回值print student_dict.setdefault(1004,"xiaozhang")# 再次输出此时student_dict字典的长度print '现在有' str(len(student_dict)) '个学生,他们分别是:'# 使用for循环遍历这个student_dict字典,分别输出这些元素for key in student_dict:print 'student_dict\[%s\]=' % key,student_dict\[key\]print '又来了一个学生"xiaoshui",给该学生分配一个该班里(字典)已用过的学生编号1004'# 使用setdefault()函数向student_dict字典添加一个(1004,"xiaoshui")的元素,并输出# 该函数的返回值print student_dict.setdefault(1004,"xiaoshui")# 再次输出此时student_dict字典的长度print '现在有' str(len(student_dict)) '个学生,他们分别是:'# 使用for循环遍历这个student_dict字典,分别输出这些元素for key in student_dict:print 'student_dict\[%s\]=' % key,student_dict\[key\]该程序运行的结果如下: 目前有三个学生刚来了一个学生"xiaozhang",给他分配的学生编号为1004xiaozhang现在有4个学生,他们分别是:student_dict\[1001\]=xiaowangstudent_dict\[1002\]=xiaolistudent_dict\[1003\]=xiaochenstudent_dict\[1004\]=xiaozhang又来了一个学生"xiaoshui",给该学生分配一个该班里(字典)已用过的学生编号1004xiaozhang现在有4个学生,他们分别是:student_dict\[1001\]=xiaowangstudent_dict\[1002\]=xiaolistudent_dict\[1003\]=xiaochenstudent_dict\[1004\]=xiaozhang从程序运行结果可以看到,第一次使用setdefault()函数向字典添加元素(1004: "xiaozhang")时,函数返回了"xiaozhang",说明元素添加成功。遍历此时的字典,可以看到元素(1004: "xiaozhang")确实已被添加到字典中。第二次又使用setdefault()函数向字典添加元素(1004: "xiaoshui")时,函数返回了"xiaozhang",说明元素添加失败。遍历此时的字典,可以看到元素(1004: "xiaoshui")确实没有被添加到字典中。这是因为添加的元素的键在字典中已存在。2. 修改元素修改字典中的元素是通过赋值语句实现的,这在添加元素里面有提到。在赋值时指定的key值在字典中要存在。#coding:utf-8# 例55修改字典# 定义一个含有3个元素(学生编号:学生)的字典student_dict={1001:"xiaowang",1002:"xiaoli",1003:"xiaochen"}# 输出初始化student_dict的字典print '初始化的字典为:',student_dict# 使用赋值语句student_dict字典中key为1001对应的值改为"xiaochen",还有key为#1003对应的值改为"xiaowang",student_dict\[1001\]="xiaochen"student_dict\[1003\]="xiaowang"# 输出修改后student_dict的字典print '修改后的字典为:',student_dict该程序运行的结果如下: 初始化的字典为: {1001: 'xiaowang', 1002: 'xiaoli', 1003: 'xiaochen'}修改后的字典为: {1001: 'xiaochen', 1002: 'xiaoli', 1003: 'xiaowang'}3. 删除元素删除字典中的元素可以通过del()函数、pop()函数或del语句实现,下面将分别介绍这几种方式。(1) 通过del()函数删除字典中的元素 该函数的语法格式如下: del(dictionary_name\[key\])其中,key表示所要删除的元素的键(key),且字典中存在这个键。(2) 通过pop()函数删除字典中的元素 该函数的语法格式如下: dictionary_name.pop(key\[,default_value\])其中,key表示所要删除的元素的键(key),如果字典中存在这个key,则函数返回key所对应的值,否则返回default_value。(3) 通过del语句删除字典中的元素 该语句的语法格式如下: del dictionary_name\[key\]其中,key表示所要删除的元素的键(key),del语句和del()函数在功能上都是一样的,在形式上只是del语句没有括号而已。注意: 使用del()函数或del语句删除不存在的元素时会抛KeyError异常,而使用pop()函数则不会。下面通过一个例子来说明这三种删除字典中元素的方式的用法。#coding:utf-8# 例56删除字典中的元素# 定义一个含有三个元素(学生编号:学生)的字典student_dict={1001:"xiaowang",1002:"xiaoli",1003:"xiaochen"}# 输出初始化student_dict的字典print '初始化的字典为:',student_dict
# 1. 使用del()函数删除字典中的键为1001的元素del(student_dict\[1001\])# 输出此时的student_dict字典print '使用del()函数删除字典中的键为1001的元素后的字典为:',student_dict
# 2.1. 使用pop()函数删除字典中的键为1001的元素(不存在)print student_dict.pop(1001,"不存在键为1001的元素")# 2.2. 使用pop()函数删除字典中的键为1002的元素(存在)print student_dict.pop(1002,"不存在键为1002的元素")# 输出此时的student_dict字典print '使用pop()函数删除字典中的键为1002的元素后的字典为:',student_dict
# 3. 使用del语句删除字典中的键为1003的元素del student_dict\[1003\]# 输出此时的student_dict字典print '使用del语句删除字典中键为1003的元素后的字典为:',student_dict程序运行结果如下: 初始化的字典为: {1001: 'xiaowang', 1002: 'xiaoli', 1003: 'xiaochen'}使用del()函数删除字典中键为1001的元素后的字典为: {1002: 'xiaoli', 1003: 'xiaochen'}不存在键为1001的元素xiaoli使用pop()函数删除字典中键为1002的元素后的字典为: {1003: 'xiaochen'}使用del语句删除字典中键为1003的元素后的字典为: {}从程序运行结果可以看到,第一次使用del()函数删除字典中键为“1001”的元素后,此时的字典有两个元素,分别为(1002,'xiaoli')和(1003,'xiaochen')。第二次使用pop()函数删除字典中键为“1001”的元素,由于此元素在字典中已不存在,所以该函数返回默认值“不存在键为1001的元素”。接下来再次使用pop()函数删除字典中键为“1002”的元素。由于此元素在字典中存在,所有该函数返回1002对应的值“xiaoli”。此时的字典只有一个元素(1003,'xiaochen')。最后使用del语句删除字典中键为“1003”的元素,可以看到此时的字典已变成空字典{}。5.1.4字典操作符适合于字典的操作符只有两个,一个是键查找操作符(\[\]),这个操作符和序列类型中的单一元素切片操作符很相似。通过这个操作符,既可以获取字典中指定的元素,也可以给字典中指定的元素赋值。这在前面的例子中已有所体现。另外一个操作符是成员关系操作符(in、not in),这个操作符和序列类型中成员关系操作符一样。下面通过一个例子来理解这两个操作符。#coding:utf-8# 例57字典操作符的使用# 定义一个含有三个元素(学生编号:学生)的字典student_dict={1001:"xiaowang",1002:"xiaoli",1003:"xiaochen"}print '初始化的字典为:',student_dictop=input("请输入对应的数字选择相应的操作(0:删除元素1:修改元素)")if op==0:key=input("请输入要删除的元素对应的键(-1表示停止删除):")while key!=-1:# 判断所输入的key在字典中是否存在if key in student_dict:# key在字典中存在,则删除该元素del student_dict\[key\]print "删除%s所对应的元素后的字典为:" % key,student_dict# 若字典长度为零,则跳出循环if len(student_dict)==0:print "字典已为空,无法继续删除元素"breakelse:print "您输入的key值(%s)在字典中不存在" % keykey=input("请输入要删除的元素对应的键(-1表示停止删除):")else:key=input("请输入要修改的元素对应的键(-1表示停止修改):")while key!=-1:# 判断所输入的key在字典中是否存在if key in student_dict:# key在字典中存在,则先输入value值,再将value值赋给要修改的元素value=raw_input("请输入要修改的值")student_dict\[key\]=valueprint "将%s赋给%s所对应的元素后的字典为:" % (value,key),student_dictelse:print "您输入的key值(%s)在字典中不存在" % keykey=input("请输入要修改的元素对应的键(-1表示停止修改):")若输入1,程序的运行结果如下(包括必要的输入): 初始化的字典为: {1001: 'xiaowang', 1002: 'xiaoli', 1003: 'xiaochen'}请输入对应的数字选择相应的操作(0:删除元素1:修改元素)1请输入要修改的元素对应的键(-1表示停止修改):1001请输入要修改的值xiaochen将xiaochen赋给1001所对应的元素后的字典为: {1001: 'xiaochen', 1002: 'xiaoli', 1003: 'xiaochen'}请输入要修改的元素对应的键(-1表示停止修改):1003请输入要修改的值xiaowang将xiaowang赋给1003所对应的元素后的字典为: {1001: 'xiaochen', 1002: 'xiaoli', 1003: 'xiaowang'}请输入要修改的元素对应的键(-1表示停止修改):1004您输入的key值(1004)在字典中不存在请输入要修改的元素对应的键(-1表示停止修改):-1该程序先输入1,表示要执行修改操作。然后输入要修改的元素对应的键(key)1001,程序使用成员关系操作符(in)来判断输入的key在字典中是否存在,如果存在,输入要修改的值“xiaochen”,再通过赋值语句修改元素的值,此时键“1001”对应的值已变为“xiaochen”。依次输入1003、“xiaowang”时,键“1003”对应的值则变为“xiaowang”。再次输入要修改的元素对应的键“1004”,由于该键在字典中不存在,所以输出“您输入的key值(1004)在字典中不存在”,然后再输入-1来退出程序。若输入0,程序的运行结果如下(包括必要的输入): 初始化的字典为: {1001: 'xiaowang', 1002: 'xiaoli', 1003: 'xiaochen'}请输入对应的数字选择相应的操作(0:删除元素1:修改元素)0请输入要删除的元素对应的键(-1表示停止删除): 1001删除1001所对应的元素后的字典为: {1002: 'xiaoli', 1003: 'xiaochen'}请输入要删除的元素对应的键(-1表示停止删除):1001您输入的key值(1001)在字典中不存在请输入要删除的元素对应的键(-1表示停止删除):1002