python程序设计 课件 第5章 字典与集合_第1页
python程序设计 课件 第5章 字典与集合_第2页
python程序设计 课件 第5章 字典与集合_第3页
python程序设计 课件 第5章 字典与集合_第4页
python程序设计 课件 第5章 字典与集合_第5页
已阅读5页,还剩83页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第5章字典与集合Python程序设计第5章字典与集合Python提供了丰富的序列类型、内置函数、方法以及语法支持等,让我们能够轻松运用序列形式的容器(数据结构)对象。但数据并非只有顺序的形式,也有“映射”形式的数据结构,即“字典”,其内含元素都是所谓的“键值配对”,从键映射到值。第5章字典与集合此外,集合也是常见的数据类型,具有严谨的数学定义,可用来存放东西(对象),但只能放进去一次,也就是记录某东西“在不在”里面。集合既非序列、也非映射,自有其一套机制,且与字典相关。有了列表与字典,几乎就可组合出绝大部分所需的数据结构。当谈到某种数据类型时,不外乎学习如何建立、存与取(写与读)、搜寻、排序、分类、过滤等等操作动作。关于杂凑1字典与集合的访问接口4字典结构2集合类型3目录5.1

关于杂凑5.1

关于杂凑杂凑(Hashing)是计算机科学中一种对数据的处理方法,通过某种特定的函数/算法(称为杂凑函数/算法),将要检索的项与用来检索的索引(称为杂凑,或者杂凑值)关联起来,生成一种便于搜索的数据结构(称为杂凑表,散列)。它也常被用作一种信息安全的实施方法,由一串数据中经过杂凑算法计算出来的数据指纹,经常用来识别文档与数据是否有被篡改。5.1

关于杂凑常见的杂凑演算法有MD5、SHA-1、SHA-256等等,可用来求得数据的数字指纹,其应用相当广泛,例如网站若提供大型文件,可一并附上该文件的杂凑值,下载后便能以杂凑值检查文件是否完整无缺。P2P(peer-to-peer)对等网络文件分享,诸如BitTorrent、eMule、BitComet,也会使用杂凑技术,借以检验下载的文件片段是否正确。杂凑因具有不可逆的性质,无法从杂凑值逆向推算原先的数据,所以也用于密码加密,当要存储密码时,并非直接存储,而是存储密码的杂凑值,即便被偷了,也无法破解得知密码。5.1

关于杂凑字典(dict)类型含有键值配对,只要是可杂凑的对象(不可变对象都可杂凑)都能作为键,所以不像列表受限于从0起跳的连续整数索引值,字典可使用不连续的大数字作为键,例如学生的学号,也可使用字符串作为键,例如汽车的车牌、日期时间、人物姓名、水果名等等;集合类型则是储存某些东西的数据结构,同样的,可杂凑的对象方能成为集合的元素。字典类型在其他程序语言里可能称为关联式阵列、杂凑表、映射等,概念相同但细节不同。字典的创建字典的键与值字典生成式全局与局部字典应用实例5.2字典结构5.2

字典结构与列表(list)是存储一个个的对象,并以索引值(从0起跳的整数)存取不同,字典是存储键值配对,透过键来存取相对应的值。建立字典时可使用大括号“{}”,里面放进以逗号隔开的键值配对,键与值则以冒号“:”隔开,存取时仍使用方括号“[]”,在方括号内放入键,便可存取相关联的值。>>>d={} #建立空字典对象>>>d={'name':'Amy','age':27} #以大括号语法建立dict对象>>>d #字典不具顺序性{'age':27,'name':'Amy'}>>>d['name'] #以方括号存取,类似于list'Amy'>>>d['age']=29 #dict是可变对象,可指派新值>>>d['score']=77 #但若是首次指派不存在的键,>>>d #便会建立该键值配对的关系{'age':29,'name':'Amy','score':77}>>>d['ape'] #但若取用时字典无此键,会发生错误Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>KeyError:'ape' #键错误5.2

字典结构5.2

字典结构图5-1示意了上述程序代码里的字典对象d,看起来跟列表很像,但字典的键不限定于整数。

字典示意图5.2.1字典的创建字典是一种映射形式的类型,从“键”映射到“值”,值可以是任何类型的对象,例如字符串、整数、列表或另一个字典,键则是不可变对象,例如字符串、整数、元组,最常使用的是字符串与整数。使用字符串的话,便能以容易记忆的字符串作为键,若键为整数的话,可使用任何范围的整数,不像表的索引值必须从0开始计数。>>>d={'str':[0,1,2],(30,41,52):{'x':0,'y':1}}>>>d[(30,41,52)] #此键是个tuple,{'x':0,'y':1} #其值是个dict>>>d={1504301:'Amy',1504305:'Bob'}>>>d[1504301] #以学号(很大的整数)作为键'Amy'5.2.1字典的创建除了以大括号包起来的字面值形式,也能透过内置函数dict(也是类型dict的构造函数)来建立字典对象,其参数的形式非常多,非常方便。>>>d=dict(name='Amy',age=40,job='writer’)#以关键字参数指定键值配对>>>d #你看到的顺序,不一定会和此处相同{'age':40,'job':'writer','name':'Amy'}>>>keys=['name','age','job'] #含有键的列表对象>>>values=['Amy',40,'writer']#含有值的列表对象>>>d2=dict(zip(keys,values)) #透过内置函数zip组合>>>d2 #虽内容物与d相同,但顺序不同{'job':'writer','age':40,'name':'Amy'}5.2.1字典的创建>>>d3=dict(d2,name='Amanda')#以d2为基础,并以关键字参数>>>d3#指定键值配对{'job':'writer','age':40,'name':'Amanda'}>>>d4=dict(zip(range(100,100+3),('Amy','Bob','Cathy')))>>>d4{100:'Amy',101:'Bob',102:'Cathy'}5.2.1字典的创建5.2.1字典的创建字典建立后,接下来便是各种支持字典的运算符与方法。>>>d={'age':29,'name':'Amy','score':77}>>>len(d) #长度,含有几个键值配对3>>>'age'ind #测试字典有无此键True>>>deld['name'] #刪除此键(以及相对应的键值配对关系)>>>'name'indFalse>>>d['name'] #以[]形式取用,若无该键会发生错误Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>KeyError:'name'>>>d.get('name')#以方法get取用,若无该键会返回None>>>d.get('name','Amy')#若无该键就返回指定的缺省值,'Amy'#注意,字典内仍无该键>>>d['name']='Amy'#以[]形式指派键值配对>>>d.setdefault('job')#以方法setdefault指派,若无该键,>>>d #缺省会指派为None{'job':None,'age':29,'score':77,'name':'Amy'}5.2.1字典的创建>>>d.setdefault('city','London') #加入此键值配对>>>d.setdefault('city') #已有此键,返回相对应的值'London'5.2.1字典的创建5.2.1字典的创建虽然字典是一种映射形式的类型,但提供了各种方法,能把键、值,甚至是键值配对以符合序列类型的对象返回,那么,我们就能用“迭代”方法逐一处理。d={'a':1,'b':2,'c':3} #类型dictforkeyind: #放在for/in循环里,会提供键的可迭代项

print(key)forkeyind.keys(): #方法keys(),提供键的可迭代项

print(key)forvalueind.values(): #方法values(),提供值的可迭代项

print(value)fork,vind.items(): #方法items(),提供键值配对的可迭代项

print(k,v)5.2.1字典的创建再强调一次,字典类型的键值配对并无顺序,就算是同样的程序代码,如果放到不同版本的Python来执行、放到另一台电脑上执行,其结果所显示的顺序不一定相同,甚至每次执行的结果都不同;换句话说,字典只提供键映射到值这样的关系而已,并不保证顺序性。字典类型的操作列于表7-1。5.2.1字典的创建表5-1字典操作5.2.2字典的键与值只要符合抽象类型Hashable(可散列)的对象,就能作为字典的键,最常用的是类型str(字符串)与int(整数);可变类型如list、set、dict,都无法作为键。注意到整数1与浮点数1.0的杂凑值相同,但因为类型float无法精确地表示大部分的浮点数,并不适合拿来作为字典的键,实际中也很少有人使用。>>>fromdecimalimportDecimal>>>fromfractionsimportFraction>>>d={1:111,'a':2,Decimal('3.14'):'pi',Fraction(1,3):1.3}>>>d{'a':2,1:111,Decimal('3.14'):'pi',Fraction(1,3):1.3}>>>hash(1.0),hash(1)(1,1) #杂凑值相同,>>>d[1.0],d[1] #所以会得到相同的对应值(111,111)5.2.2字典的键与值5.2.2字典的键与值若键是字符串,也能使用构造函数dict来建立字典对象,但因为需要以参数的形式传入,所以该键(字符串)必须符合Python的识别字规则,例如字符串'123abc'就无法以此形式建立。>>>dict(foo=1,bar=2,abc123=3)#以关键字参数传入键与值{'foo':1,'bar':2,'abc123':3}>>>dict(foo=1,bar=2,123abc=3)#123abc不符合识别字规则

File"<stdin>",line1dict(foo=1,bar=2,123abc=3)^SyntaxError:invalidsyntax>>>d={'foo':1,'bar':2,'123abc':3} #以这种形式就没问题了{'foo':1,'bar':2,'123abc':3}>>>d2=dict(d,foo=555,abc=999) #以先前的字典d为基础,>>>d2#再以关键字参数新增或更新键值配对{'foo':555,'abc':999,'bar':2,'123abc':3}>>>k=['foo','bar'];v=[101,102] #以zip合并两个列表,>>>d3=dict(zip(k,v),abc=999) #便可作为键值配对的提供者>>>d3{'foo':101,'abc':999,'bar':102}5.2.2字典的键与值5.2.2字典的键与值另外也能以字典类型的方法fromkeys来建立列表,此方法不属于某一个实体对象,所以称为类型方法。其首个参数可以是序列对象(或可迭代项),提供键,后一个参数(选用性)则是缺省值,若不指定则会是None。>>>dict.fromkeys(['a','b','c']){'a':None,'b':None,'c':None}>>>dict.fromkeys(['a','b','c'],999){'a':999,'b':999,'c':999}>>>dict.fromkeys(range(5),0){0:0,1:0,2:0,3:0,4:0}5.2.3字典生成式用来建立字典对象的字典生成式与列表生成式非常类似,只是语法稍有不同,它使用大括号“{}”包起来,在for的左边必须是“k:v”的形式,提供键值配对;同样地,也能加上if进行过滤。{表达式:表达式for名称in可迭代项}{表达式:表达式for名称in可迭代项if表达式}>>>{k:k**2forkinrange(5)} #键从0到4,值是平方{0:0,1:1,2:4,3:9,4:16}>>>dict([(k,k**2)forkinrange(5)]) #使用列表生成式与构造函数dict,{0:0,1:1,2:4,3:9,4:16} #达到同样的效果>>>d={'Amy':90,'Joe':45,'Kevin':33}>>>{k:vfork,vind.items()ifv<60}#仅拿出成绩低于60的{'Joe':45,'Kevin':33}>>>li=['a','b','c']>>>{a:ifori,ainenumerate(li,start=101)}{'a':101,'b':102,'c':103} #为每个元素賦予某列举值>>>dict(enumerate(li,start=1)) #呃,不一样...{1:'a',2:'b',3:'c'}>>>dict(zip(li,range(101,101+len(li))))#弄出相同的字典了{'a':101,'b':102,'c':103}5.2.3字典生成式5.2.3字典生成式虽然某些字典生成式能以列表生成式与构造函数dict改写,但后者必须先建立列表对象,然后再传入构造函数dict,效能较为缓慢,从语法来看也较不简洁。5.2.4全局与局部Python会把“名称”放在命名空间里,也就是把名称与对象的绑定关系存储在字典里。【程序实例5-1】全局与局部命名空间。#symbol_table.pya=1b=2c=3deffoo(x,y):a='aaa'b='bbb'print(locals())print(globals())print('*'*10)foo(80,91)5.2.4全局与局部5.2.4全局与局部名称a、b、c、foo被放在全局命名空间里。若调用函数foo,会进入函数局部范围,名称x、y、a、b会被放在局部的命名空间里。以Python内置函数globals取得含有全局名称(与对象绑定关系)的字典,也称为全局符号表,以locals取得含有局部名称的字典(局部符号表)。上述程序代码执行后,会输出如下的信息:{'a':1,'c':3,'b':2,'__builtins__':<module'builtins'(built-in)>,'__file__':'symbol_table.py','__package__':None,'__cached__':None,'__name__':'__main__','foo':<functionfooat0x7fe2d8ec>,'__doc__':None}**********{'a':'aaa','y':91,'b':'bbb','x':80}5.2.4全局与局部在全局字典里,你可看到名称a、b、c、foo以及一些其他名称,例如__file__指向文件名的字符串,__name__则是目前所在模块名,而__builtins__则指向内置模块,也因为有它,Python才知道要去哪寻找内置的函数、常数、异常。在局部字典里,可看到x、y、a、b,因字典不具顺序性,所以并不会按照参数的顺序、赋值语句的先后顺序排列名称。5.2.5字典应用实例若需要根据某对象的内容拿出相对应的数据或执行不同的程序代码,往往会使用if/elif/elif.../else来实作,但可能太过冗长;可以把东西先放进字典,然后直接取用即可。x='apple'result=Noneifx=='apple': #以一连串的if/elif.../else来做判断,

result=1elifx=='banana':result=2elifx=='grape': #该执行哪部分的程序代码

result=3else:result=-1####上述程序代码可改写为:####x='apple'd={'apple':1,'banana':2,'grape':3}result=d.get(x,-1)5.2.5字典应用实例5.2.5字典应用实例因为函数也是对象,也可作为值放进字典里,这样一来便可根据键来执行相对应的程序码,例如:deff0():pass #准备一些函数deff1():passdeff2():pass #作为值放进字典里d={'apple':f0,'banana':f1,'grape':f2}x='apple'ifxind: #若有该键,

d[x]() #便取出对应的值(函数对象)并调用执行若字典的值可杂凑,便可逆转键值配对。不过若值重复的话,逆转后将会只剩一个键值配对。【程序实例5-2】逆转字典的键值配对。#dict_invert.py#学生姓名与成绩d={'Amy':45,'Bob':50,'Cathy':62,'David':45,'Eason':63,'Fred':78,'George':72,'Helen':82,'Ivan':100,'Jason':98,'Kevin':0,'Laura':100}#逆转键值配对d2={v:kfork,vind.items()}#逆转后,键100、值可能会是'Laura'或'Ivan',只剩一个5.2.5字典应用实例5.2.5字典应用实例因为字典不具顺序性,若想要按照某种排序方式输出或操作字典的话,可运用内置函数sorted来排序。可再传入一个名为key的参数,由它来指定根据什么来排序。【程序实例5-3】排序字典。#dict_sort.py#键是学生姓名,值是一个含有三项成绩的tuple对象,假设成绩依序是数学、历史、英文d={'Amy':(45,60,33),'Bob':(50,62,78),'Cathy':(62,98,87),'David':(45,22,12),'Eason':(63,55,71),'Fred':(78,79,32)}forkinsorted(d.keys()): #根据键(姓名)排序

print(k,d[k])5.2.5字典应用实例deffoo(item):returnitem[1][2] #根据英文成绩来排序foriteminsorted(d.items(),key=foo):print(item)defbar(item):returnsum(item[1]) #根据总分来排序foriteminsorted(d.items(),key=bar):print(item)5.2.5字典应用实例5.2.5字典应用实例字符串格式化,包括运算符“%”与字符串方法format,都可以运用字典。集合的创建集合的元素集合的数学运算集成生成式5.3集合类型5.3

集合类型接下来,我们来看看类型set(集合)。集合是一种不具顺序性的容器类型,同一个对象只能放进去一次。建立集合时,字面值语法是以大括号“{}”包住想要的一个个元素,或调用内置函数set,传入可迭代项(提供一个个元素)。元素可以是任何不可变对象,例如int、tuple、str。>>>x={1,2,3,4,5} #以大括号包住集合元素>>>x{1,2,3,4,5}>>>x2=set([1,'a',(3,4),5]) #内置函数set,传入含有元素的列表>>>x2{1,'a',(3,4),5}>>>x3=set(range(1,5+1)) #内置函数set,传入含有元素的可迭代项>>>x4={0,1,[2,3,4]} #list是可变对象,发生错误Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:unhashabletype:'list'5.3

集合类型5.3

集合类型上述程序中,x2对象的示意如图所示。与字典相同,集合内的元素也不具有顺序性,类型set仅代表某东西是否存在于该集合内。

集合示意>>>x={};type(x) #{}会建立空字典,不是空集合<class'dict'>>>>x={1,2,3,4,5}>>>x[0] #集合不具顺序性,不支持索引存取方式Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:'set'objectdoesnotsupportindexing>>>len(x) #长度,集合内元素的个数5>>>1inx #判断某对象存不存在于集合内True5.3

集合类型>>>x.add(6) #加入新元素>>>x.add(6) #加入已有的元素,无作用>>>x.remove(1) #移除某元素>>>x.remove(7) #若该元素不存在于集合内,发生错误Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>KeyError:7>>>x.discard(7) #移除某元素,若不存在并不会发生错误>>>x{2,3,4,5,6}5.3

集合类型>>>x&{5,6,999} #“&”运算符,交集(intersection){5,6}>>>x|{5,6,999} #“|”运算符,联集(union){2,3,4,5,6,999}>>>x-{5,6,999} #“-”运算符,差集(difference){2,3,4}>>>x^{5,6,999} #“^”运算符,对称差集(symmetricdifference){2,3,4,999}5.3

集合类型5.3

集合类型当想检查两个列表是否含有相同的元素,但不在乎顺序与是否重复时,便可利用类型set,非常便利。>>>li0=[0,1,2];li1=[2,2,1,0,2,1]#不同的列表>>>set(li1) #传入内置函数set,得到不重复元素的集合{0,1,2}>>>set(li0)==set(li1) #以集合的眼光来看是相等的True5.3

集合类型集合类型是一种不具顺序性的容器类型,其元素必须是可杂凑的对象,记录某对象在不在集合里。因为不具顺序性,所以集合不支持索引与切片的存取方式。5.3.1集合的创建建立集合时,可使用被圆括号“()”包住、以逗号“,”隔开元素的字面值形式,或是使用类型set的构造函数。调用构造函数set时,参数是个可迭代项,负责提供一个个的元素,元素必须可杂凑。>>>empty_dict={} #这是空字典>>>empty_set=set() #这才是空集合>>>{'a','b','c'} #含有三个元素的集合{'c','b','a'} #集合不具顺序性>>>{(0,1,2),3,3.14} #元素可以是任何不可变对象{(0,1,2),3.14,3}>>>set('abc') #使用构造函数set,传入序列对象{'c','b','a'}>>>set([30,41,52]) #传入列表{41,52,30}5.3.1集合的创建>>>set(range(5)) #传入可迭代项{0,1,2,3,4}>>>s0=set(range(5))>>>set(s0) #传入另一个集合对象{0,1,2,3,4}>>>len(s0) #长度5>>>1ins0 #判断里面是否含有某元素True5.3.1集合的创建5.3.2集合的元素集合建立后,因为是可变对象,可使用集合专属的方法原地修改其元素。>>>s={0,1,2,3,4,5}>>>s.add(6) #加入int对象6>>>s.add(3) #加入已有的元素,无作用>>>s.remove(0) #移除0>>>s{1,2,3,4,5,6}>>>s.remove(999) #若想移除的元素不存在,引发异常Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>KeyError:9995.3.2集合的元素>>>s.discard(999) #使用discard的话,元素不存在不会引发异常>>>s.pop() #随机移除某元素、返回该元素2>>>s{3,4,5,6}>>>s1=s.copy() #浅复制>>>s.clear() #清空集合>>>s.pop() #若集合为空,pop会引发异常Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>KeyError:'popfromanemptyset'5.3.2集合的元素5.3.3集合的数学运算集合有严谨的数学定义,Python也以运算符和方法支持集合的数学运算,包括联集、交集、差集、对称差集以及子集合、超集合的判断。>>>s0={1,2,3,4} #测试用集合>>>s1={3,4,5,6,7}>>>s2={1,2,3}>>>s3={91,92,93}>>>s0==s1,s0==s0 #判断是否含有同样的元素(False,True)>>>s2<=s0,s2.issubset(s0) #子集合(True,True)>>>s2<s0,s0<s0 #真子集合(True,False)5.3.3集合的数学运算>>>s0>=s2,s0.issuperset(s2) #超集合(True,True)>>>s0>s2,s0>s0 #真超集合(True,False)>>>s0|s1 #联集,产生新集合对象{1,2,3,4,5,6,7}>>>s0&s1 #交集,产生新集合对象{3,4}>>>s0-s1 #差集,产生新集合对象{1,2}5.3.3集合的数学运算>>>s0^s1 #对称差集,产生新集合对象{1,2,5,6,7}>>>s0&s3,s0.isdisjoint(s3) #无交集(set(),True)5.3.3集合的数学运算5.3.3集合的数学运算同一种集合运算,例如联集,有运算符“|”与方法“union”可用,但运算符只能接受集合对象,而方法则可接受可迭代项,例如列表。>>>s0={1,2,3,4}>>>s0|[3,4,5,6] #运算符只能接受集合对象Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:unsupportedoperandtype(s)for|:'set'and'list'>>>s0.union([3,4,5,6]) #方法可以接受可迭代项{1,2,3,4,5,6}>>>set('abc')&'bcd'Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:unsupportedoperandtype(s)for&:'set'and'str'>>>set('abc').intersection('bcd'){'c','b'}5.3.3集合的数学运算5.3.3集合的数学运算使用增强型赋值语句“|=、&=、-=、^=”时须小心,这是原地修改的动作,不会产生新集合对象,而是更新(修改)语句左边的集合对象。>>>s0={1,2,3,4}>>>s0|={3,4,5,6} #只示范“|=”,其余都类似>>>s0{1,2,3,4,5,6}5.3.4集合生成式集合也有集合生成式可用,其语法和列表生成式、字典生成式类似,一般形式如下:{表达式for名称in可迭代项}{表达式for名称in可迭代项if表达式}>>>li=['a','bar','candy','o','car']>>>{len(x)forxinli}{1,3,5} #记录曾出现过的字符串长度>>>{xforxinliiflen(x)==1}{'a','o'} #只收录长度为1的字符串>>>li=[0,1,1,2,2,3,3,4,5,5,6]>>>{xforxinliifli.count(x)==2}{1,2,3,5} #挑出在原列表出现2次的元素5.4字典与集合的访问接口可杂凑项映射5.4

字典与集合的访问接口在学习了字典与集合的基本知识后,我们来介绍相关的抽象类型,了解字典与集合提供哪些存取接口。5.4.1可杂凑项之前介绍类型dict时,我们说“键”可以是任何不可变对象,这种说法还不够正确,应该说任何“可杂凑项(hashable)”都可作为字典的键。Python有个抽象类型Hashable,符合此接口的对象可依照杂凑演算法算出独一无二的杂凑值,只要对象不相同,就会得到不同的杂凑值。Python内置的不可变类型都符合此抽象类型,而内置的可变类型则都不符合。调用内置函数hash可得到某对象的杂凑值,但实际中很少直接使用该值。>>>fromcollections.abcimport*>>>issubclass(int,Hashable) #内置的不可变类型都符合Hashable接口True>>>issubclass(tuple,Hashable)True>>>issubclass(list,Hashable) #内置的可变类型,不符合Hashable接口False #因为可变对象的内容会改变,其杂凑值不定>>>issubclass(dict,Hashable)False>>>hash(1),hash('abc'),hash((30,41,52))(1,-39521455,1696699620) #不可变对象拥有独一无二的杂凑值5.4.1可杂凑项>>>a=1;b='abc';c=(30,41,52)>>>hash(a),hash(b),hash(c) #既然a==1为真,内容相同,(1,-39521455,1696699620) #那么其杂凑值也会相同>>>hash([0,1,2]) #不可变对象没有杂凑值Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:unhashabletype:'list'>>>hash('name'),hash('age'),hash('score')(1574142124,537780116,-23663026)>>>hash(1),hash('a'),hash((3,4)),hash(5)(1,738615097,1699342716,5)5.4.1可杂凑项5.4.1可杂凑项不可变对象在其生存周期内内容绝对不变,所以其杂凑值不仅独一无二,而且也不会改变,可作为字典的存储依据;所以较正确的字典示意图应如图所示,字典其实是存储“对象的杂凑值”与“值(任何对象)”的配对关系。下次当你给定某键时,字典就会算出该键的杂凑值,然后取出相对应的值。

字典示意图5.4.1可杂凑项若对象属于容器类型,那么不仅对象本身必须不可变,其内容也必须不可变,方可算是不可变对象。所以,tuple对象本身虽不可变,但若含有可变对象(例如list),那么该对象就不算是不可变,无法作为字典的键。>>>li=[0,1,2] #list对象,可变>>>t=(3,4,li) #tuple对象,含有可变对象>>>d={'a':1,t:2} #无法作为字典的键Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:unhashabletype:'list'5.4.1可杂凑项同样的道理,类型set也不是直接存储某对象,而是存储杂凑值。当把某对象放进集合时,会先算出杂凑值再放进去;当要测试某对象存不存在集合内时,只要算出对象的杂凑值,然后再检查即可(见图示意)。

集合示意图5.4.1可杂凑项因为杂凑演算法的特性,给定某内容(对象)就算出相对应的杂凑值,若对象不同就必定会得到不一样的杂凑值,如此一来便能轻松得到字典与集合的功能。还请注意,不同Python版本可能会使用不同的杂凑演算法,不同平台的Python实现也可能使用不一样的杂凑演算法,所以你执行上述程序时,不会得到跟实例一样的杂凑值。5.4.2映射项图7-5显示了与以映射(Mapping)为中心的相关抽象类型,类型dict符合抽象类型MutableMapping(可变映射)定义的接口,而且dict也是目前Python唯一的内置映射类型;类型set符合抽象类型Set定义的接口。

映射相关的抽象类型层级5.4.2映射项我们先从类型set的抽象类型Set着手,因为它是个容器类型,很自然地继承了抽象类型Sized与Container,所以可使用内置函数len算出长度(含有元素个数),并以运算符“in”检查某对象是否存在于集合之中。而且也符合可迭代项接口,所以可使用内置函数iter得到迭代器,然后调用next逐一取出其中的元素,只不过因为类型set不具顺序性,所以我们并不知道迭代器会以何顺序给出元素。>>>x={2,'a',(3,5),'b',17} #类型set>>>len(x) #长度,元素的个数5>>>'b'inx #成员关系运算符True>>>xit=iter(x)#取得迭代器>>>next(xit),next(xit)#取出前两个元素,(17,'a')#注意,不具顺序性>>>[eforeinxiftype(e)isint]#既然符合Iterable接口[17,2] #所以可用于需要迭代协定的地方5.4.2映射项5.4.2映射项然后是类型dict符合的接口面,抽象类型Mapping(映射)与MutableMapping(可变映射),同样的,因为属于容器类型,所以也都继承了Sized与Container,并拥有许多字典专属的方法。>>>d={'name':'Amy','age':40,'score':77}>>>len(d) #长度,键值配对的个数3>>>'age'ind #“in”运算符,某键是否存在True>>>d['name'] #以键取出值'Amy'>>>d['job']='wrier' #重新指派,新增或更新>>>d.pop('name') #移除指定键(与其键值配对)'Amy'5.4.2映射项>>>d.pop('abc') #若不存在该键,发生错误Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>KeyError:'abc'>>>d.pop('abc','default')#指定不存在该键时应返回的缺省值'default'

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论