系列4python之详细初学者教程讲义-7.映射与集合_第1页
系列4python之详细初学者教程讲义-7.映射与集合_第2页
系列4python之详细初学者教程讲义-7.映射与集合_第3页
系列4python之详细初学者教程讲义-7.映射与集合_第4页
系列4python之详细初学者教程讲义-7.映射与集合_第5页
免费预览已结束,剩余47页可下载查看

下载本文档

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

文档简介

映射类型:字Python型。字典类型和序列类型容器类(列表、元组)的区别是和数据的方式不同。序列类型只用的是用字符串做键(keys)。和序列类型的键不同,映射类型的键(keys)直接,或间接地和的数笔记:什么是哈希表?它们与字典的关系是什用字将组式索毫无关系。还可以用另 式来 数据:基于某种相关值,比如说一个字符串。我们在日常一直这么做。你把人们的按照他们的姓记录在簿上,你按照时间在日历或簿上添加事件,等等。在这些例子中,你的键(key)就是和数据项相关的值。哈希表是一种数据结构:它按照我们所要求的去工作。哈希表中的每一条数据,叫做一个(value),是根据与它相关的一个被称作为键(key)的数据项进行的。键和值合在一起被称为“键-值对”(key-valuepairs)。哈希表的算法是获取键,对键执行一个叫做哈希函数的操作,并根据计算的结果,选择在数据结构的某个地址中来你的值。任何一个值的地址皆取决于它的键。正因为这种随意性,哈希表中的值是没有顺序的。你拥有的是一个无序的数据集。你所能获得的有序集合只能是字典中的键的集合或者值的集Keys()values()返回一个列表,该列表是可排序的。还可以items()方法得到包含键、值对的元组的列表来排序。哈希表一般有很好的性能,因为用键查询相当被包含在({})里。如何创建字典和给字>>>dict1=>>>dict2={'name':'earth','port':>>>dict1,({},{'port':80,'name':会看到的例子,现在来看一个小例子:>>>fdict=dict((['x',1],['y',>>>{'y':2,'x':典中元素具有相同的值(如果没有给出,默认为None):>>>ddict={}.fromkeys(('x','y'),->>>{'y':-1,'x':->>>edict={}.fromkeys(('foo',>>>{'foo':None,'bar':如何字典中的>>>dict2={'name':'earth','port':>>>>forkeyin...print'key=%s,value=%s'%(key,key=name,value=earthkey=port,value=80Python2.2keys()用迭代器来轻松地类序列对象(sequence-likeobjects),比如字典和文件。只需要用字典的名字就可以在for循环里遍历字典。>>>dict2={'name':'earth','port':>>>>forkeyin...print'key=%s,value=%s'%(key,key=name,value=earthkey=port,value=80>>>dict2['name']>>>print'host%sisrunningonport%d'%...(dict2['name'],dict2['port'])hostearthisrunningonport80对应的值分别是'earth'和80。就像你看到的,通过键'name'>>>dict2['server']Traceback(innermostlast):File"<stdin>",line1,in?KeyError:has_key(种比较好的方法就是从2.2版本起用的,in或notin操作符。has_key()方法将会在未来的Pythonin或notin下面介绍字典所有的方法。方法has_key()和in以及notin操作符都是布尔类型的。没有布尔常量,为真时返回1,假时返回0。)>>>'server'indict2#或dict2.has_key('server')'name'indictdict2.has_key('name')>>>dict2['name']>>>dict3=>>>dict3[1]=>>>dict3['1']=>>>dict3[3.2]=>>>{3.2:'xyz',1:'abc','1':dict3={3.2:'xyz',1:'abc','1':为什么在执行中字典中的键不允许被改变呢?你这样想就会明白:比方说,你创建了一个字KeyError(因为键的值已经改变了),现在你没办7.5.2如何更新>>>dict2['name']='venus'#dict2['port']6969#更新已有>>>dict2['arch']='sunos5'#hostvenusisrunningonport6969print如何删除字典元素和del3.5.5deldict2['name']#删除键为“name”的条目dict2.clear()#删除dict2所有的条目deldict2整个dict2dict2.pop('name')#删除并返回键为“name笔记:避免使用内建对象名字作为变量如果Python2.3前,你已经开始Python,你可能用dict作为一个字典的标识但是,因dict()在已成Python类型和工厂方法,重载dict()会给你带来麻烦和潜bugs。编译器允许你做这样的重载它认为你是聪明的知道自己正在做什么请不要用dict,list,file,bool,str,input,len这样的内建类型为变量命名。映射类型操作字典可以和所有的标准类型操作符一起工作,但却不支持像拼接(concatenation)和重复标准类型操作>>>dict4={'abc':>>>dict5={'abc':>>>dict6={'abc':123,98.6:>>>dict7={'xyz':>>>dict4<dict5>>>(dict4<dict6)and(dict4<dict7)>>>(dict5<dict6)and(dict5<dict7)>>>dict6<dict7算法请见第7.3.1小节。映射类型操作字典的键查找操作符([对字典类型来说,是用键(key)查询(字典中的元素),所以键是参数(argument),d[k]=v (键)成员关系操in,notPython2.2has_key()innotin映射类型的内建函数和工厂函标准类型函数[type()、str()和如你所料,对一个字典调用type()工厂方法,会返回字典类型,“<type'dict'>”.调用是值。可是,用cmp()做字典的比较一般不是很有用。*字典比较算>>>dict1=>>>dict2={'host':'earth','port':>>>cmp(dict1,->>>dict1['host']=>>>cmp(dict1,-加一个元素后,dict1dict2(2vs.1),dict2>>>dict1['port']=>>>cmp(dict1,dict2)>>>dict1['port']=>>>cmp(dict1,dict2)在向dict1中添加第二个元素后,两个字典的长度相同,所以用键比较大小。这时键相等,则'portdict相同的键、相同的值,所以cmp()返回值是0。dict2isdeemedlargerbecauseitsvalueisgreaterthanthatofdict1’sport'key8080vs80dict1isdeemedlargerbecauseitsvalueisgreaterthanthatofdict2’s'port'key(8080vs.80).}>>>dict1['prot']=>>>cmp(dict1,dict2)>>>dict2['prot']=>>>cmp(dict1,->>>cdict=>>>ddict=>>>cmp(cdict,ddict)>>>cdict['oranges']=>>>ddict['apples']=>>>cmp(cdict,cmp(dict2dict1len(dict1)>len(dict2)==>dict1>keys()方法返回键的顺序相同。(注意:相同的键会映射到哈希表的同一位置,这保证了对字典键的检查的一致性。)这时,dict1于dict2中第一个不同的键,cmp()会返回正值。dict1dict2Exact返回0值。7-17-1映射类型相关的函二个元素是字典中的值。见Python文档里关于dict()的例子:>>>dict(zip(('x','y'),(1,{'y':2,'x':>>>dict([['x',1],['y',{'y':2,'x':>>>dict([('xy'[i-1],i)foriin{'y':2,'x':内容来生成新的字典。新生成的字典是原来字典对象的浅版本,它与用字典的内建方法推荐使用copy()。>>>dict(x=1,{'y':2,'x':>>>dict8=dict(x=1,>>>{'y':2,'x':>>>dict9=>>>{'y':2,'x':我们提醒读者dict9的例子只作为了解dict()方法的用途,它不是现实中的例子。使用下面这些行的方法(效率更好):>>>dict9=>>>{'y':2,'x':调用len(),它会返回所有元素(键-值对)的数目:>>>dict2={'name':'earth','port':>>>{'port':80,'name':>>>len(dict2)hash(),才可作为字典的键(函数的返回值是整数,不产生错误或异常)。>>>Traceback(innermostlast):File"<stdin>",line1,in?TypeError:listobjectsareunhashable>>>dict2[{}]=Traceback(mostrecentcalllast):File"<stdin>",line1,inTypeError:dictobjectsare表 映射类型的相关函函 操 创建字典的工厂函数。如果提供了容器类(container) 返回obj的哈希值映射类型内建方字典提供了大量方法来帮你做事情,见表has_key()替代方法in和notin7.1KeyError键,values()方法,返回一个列表,包含字典中所有的值,items(),>>>dict2.keys()['port',>>>dict2.values()[80,'earth']>>>[('port',80),('name',>>>foreachKeyin print'dict2key',eachKey,'hasvalue',dict2keyporthasvalue807.2方法名 操 val=None)c 典中所有键对应的初始值(如果不提供此值,则默认为None) 对字典dict中的键key,返回它对应的值value,如果字典中不存在此defaultdefaultNone)dict.has_key(key)如果键(keyTrueFalse.Python2.2innotindict.items()dict.keys() 方法iteritems(),iterkeys(),itervalues()与它们对应的非迭代方法[,default])c 和方法get()相似,如果字典中key键存在,删除并返回dict[key], Python1.5Python2.3Python2.2Python2.0在Python2.4keys(sort()sorted()的内建函数,它返回>>>foreachKeyin...print'dict2key',eachKey,'hasvalue',dict2keynamehasvaluedict2keyporthasvalue>>>dict2={'host':'earth',>>>dict3={'host':'venus',>>>>>>{'server':'http','port':80,'host':>>>>>>后要说明,get()方法和键查找(key-lookup)操作符([])相似,不同的是它允许你为不存在的键提供默认值。如果该键不存在,也未给出它的默认值,则返回None。此方法比采用键查找(key-lookup)更灵活,因为你不必担心因键不存在而异常。>>>dict4=>>>{'server':'http','port':80,'host':>>>dict4.get('host')>>>>>><type>>>dict4.get('xxx','nosuchkey')'nosuchkey'setdefault(2.0中是否含有某键。如果字典中这个键存在,你可以取到它的值。如果所找的键在字典中不存在,你可以给这个键赋默认值并返回此值。这正是执行setdefault()方法的目的:>>>myDict={'host':'earth','port':>>>myDict.keys()['host',>>>[('host','earth'),('port',>>>myDict.setdefault('port',>>>myDict.setdefault('prot','tcp')>>>[('prot','tcp'),('host','earth'),('port',>>>{'y':None,'x':None,'z':>>>{}.fromkeys(('love','honor'),{'love':True,'honor':目前,keys(),items(),和values()方法的返回值都是列表。数据集如果很大会导致很难iteritems(),iterkeys(),itervalues()Python2.2因。这些函数与返回列表的对应方法相似,只是它们返回惰性赋值的迭代器,所以节省内存。未来Python(views)。视图(views)是容器对象的接口集。举例来说,你可以从一个视图(views)中删除某个字典的键,从字典的Python不允许一个键对应多个>>>dict1={'foo':789,'foo':>>>{'foo':>>>dict1['foo']=>>>{'foo':'foo'被列出两次,Python从左到右检查键-值对。首先值789被赋值(给键'foo'所对应的值),然后键已经存在(键),那此键所对应的值将被替换。上面例子中,键'foo'所对应的值被替换了两次;最后的赋值语句,值123代替了值'xyz'。键必须是可哈希我们在小节7.1,大多数Python对象可以作为键;但它们必须是可哈希的对象。像列表和11.0一个实现了hash()特殊方法的类。因为hash()方法返回一个整数,所以仍然是用不可变为什么键必须是可哈希的?解释器调用哈希函数,根据字典中键的值来计算你的数据的位置。如果键是可变对象,它的值可改变。如果键发生变化,哈希函数会映射到不同的地址来数据。如果这样的情况发生,哈希函数就不可能可靠地或获取相关的数据。选择可哈希的键的原因就是因为它们的值不能改变。(此问题在PythonFAQ中也能找到答案)6.17.2,我们用一个程序(userpw.py7.1理用户名和的模拟登录数据系统。接受新用户的信息:示例7.11#!/usr/bin/env23db={}prompt='logindesired:whilename=ifprompt='nametaken,tryanother:pwd=raw_input('passwd:defname=raw_input('login:pwd=raw_input('passwd:passwd=ifpasswd== back',print'loginincorrect'def prompt=(N)ewUser(E)xistingUserExample7.1DictionaryExample(userpw.py)(continued) done=chosen=whilenotchoice=except(EOFError,choice=print'\nYoupicked:[%s]'%ifchoicenotinprint'invalidoption,trychosen=done=505153 =='main LinesLinesnewuser()函数用来建立新用户。它检查名字是否已经存在,如果证实是一个新名字,将要求用户输入他或(我们这个简单的程序没有加密),用户的被在字典里,以他们的名 17–24Lines真正控制这个的是show()函数,它显示给用户一个友好界面。提示信息被包括在三引'\n'符号的字符串更容易处理。菜单显queue.py例子里的一样(见小节6.14.1).Lines如果这个被直接执行(不是通过import方式),这行代码会调用show 这是我们的运行结果:$userpw.py(E)xistingUserLoginYoupicked:logindesired:kingpasswd:(N)ewUserLogin(E)xistingUserLoginEnterchoice:Youpicked:[e]login:sirknightpasswd:fleshwoundloginincorrect(N)ewUserLogin(E)xistingUserLoginEnterchoice:Youpicked:[e]login:kingarthurpasswd:grailbackking(N)ewUserLogin(E)xistingUserLoginYoupicked:集合类数学上,把set称做由不同的元素组成的集合,集合(set)的成员通常被称做集合元素(setintersection等操作符在Python里也同样如我们所预想地那样工作。innotinlen()for集合(sets)有两种不同的类型,可变集合(set)和不可变集合(frozenset)。如你所想,对可变集合(set(frozenset)则不允许这样做。请注意,可变集合(set)不是可哈希的,因此既不能用做字典的键也不能做其他集合中的元素。不可变集合集合(Sets)最早出现在Python2.3版本中,通过集合(sets)模块来创建,并通过ImmutableSet类和Set类进行。而后来,大家都认为把它们作为内建的数据类型是个更好的主意,因此这些类被用C重写改进后包含进Python2.4。关于集合类型和这些类改进的内容,可阅读此文获得详情:PEP218,地址:.PythonPython以把它们作为真正集合类型的来使用。因此现在的使用者有包括“真正”集合类型在内的多种在我们详细讲述Python的集合对象之前须理解Python中的一些数学符号(见表7.3),7.3数学符 Python符 说集合类如何创建集合类型和给集的工厂方法list()dict()set()和>>>s=>>>set(['c','e','h','o','p',>>>t=>>>frozenset(['b','h','k','o','p',>>><type>>><type>>>len(s)==>>>s==如何集合中的>>>'k'ins>>>'k'int>>>'c'notint>>>foriin print如何更新>>>>>>set(['c','e','h','o','p','s',>>>>>>set(['c','e','i','h','o','p','s','y',>>>>>>set(['c','e','i','h','o','p','s',>>>s-=>>>set(['c','e','h','o',>>>Traceback(mostrecentcalllast):File"<stdin>",line1,in?AttributeError:'frozenset'objecthasnoattribute如何删除集合中的成Python会被标记以便被回收。>>>del集合类型操作标准类型操作符(所有的集合类型成员关(in,not>>>s=>>>t=>>>'k'ins>>>'k'int>>>'c'notint集合等价/不等stst(True),或(s<=tands>=t)的值为真(True)。集合等价/不等价与集合的类型或集合成员的顺序无关,>>>s==>>>s!=>>>u=>>>s==>>>set('posh')==子集SetsPythonSets((超集。只有当第一个集合是第二个集合的严格子集时,我们才称第一个集合“小于”第二个集合,>>>set('shop')<set('cheeseshop')>>>set('bookshop')>=set('shop')集合类型操作符(所有的集合类型联合|联合(unionOR(又称可兼析取(inclusivedisjunction))其实是等价的,两个集>>>s|set(['c','b','e','h','k','o','p',交集&个元素同时是两个集合中的成员,即,属于两个集合的成员。交集符号有一个等价的方法,>>>s&set(['h','s','o',差补/相对补于集合t。差符号有一个等价的方法,difference().>>>s-tset(['c',对称差分^两个集合(stCst>>>s^set(['k','b','e',混合集合st>>>t|frozenset(['c','b','e','h','k','o','p',>>>t^frozenset(['c','b','e',>>>t-sfrozenset(['k',set,frozenset,>>>v=s+Traceback(mostrecentcallFile"<stdin>",line1,inTypeError:unsupportedoperandtype(s)for+:'set'and>>>v=s|>>>set(['c','b','e','h','k','o','p',>>>s<v集合类型操作符(仅适用于可变集合(Union)Update(|=>>>s=>>>u=>>>s|=>>>set(['c','e','i','h','o','p','s',保留/交集更&=>>>s=>>>s&=>>>set(['h','s','o',差更除掉集合t中元素后剩余的元素。此方法和difference_update()等价.>>>s=>>>s-=>>>set(['c',对称差分更^对集合s和t进行对称差分更新操作(s^=t),对称差分更新操作会返回一个集合,该集合中的成>>>s=>>>t=>>>s^=>>>set(['c','b','e',内建函标准类型函>>>s=>>>set(['p','c','e','h','s',集合类型工厂函set()andset(frozenset()工厂函数分别用来生成可变和不可变的集合。如果不提供任何参数,默认>>>>>>>>>set('shop')set(['h','s','o','p'])>>>frozenset(['foo',frozenset(['foo',>>>f=open('numbers',>>>foriin...f.write('%d\n'%>>>>>>f=open('numbers',>>>set(['0\n','3\n','1\n','4\n',>>>集合类型内建方方法(所有的集合方法7.4内建方法copy()没有等价的操作符。和同名的字典方法一样,copy()方法比用像set(),frozenset(),或dict()这样的工厂方法对象的副本要快。表7.4 如果t是s的超集,则返回True,否则返回False 返回一个新集合,该集合是s和t的并集ersection(t)返回一个新集合,该集合是s和t的交集 st 方法(仅适用于可变集合7.5新的方法有add(),remove(),discard(),pop(),clear().这些接受对象的方法,参数必操作符和内建方法比像你看到的,很多内建的方法几乎和操作符等价。我们说"几乎等价",意思是它们间是有一个重要区别:当用操作符时,操作符两边的操作数必须是集合。在使用内建方法时,对象也可以是迭代类型的。为什么要用这种方式来实现呢?Python的文档里写明:采用易懂的set('abc').intersection('cbs')可以避免用set('abc')[and]'cbs'这样容易出错的构建方7.5方法 操 ersection_update(t)s中的成员是共同属于s和t的元素。 s中的成员是属于s但不包含在t中的元素s.symmetric_difference_update(t)s中的成员更新为那些包含在s或t中,但 是t ins),将KeyError错误 删除集合s中的任意一个对象,并返回它 操作符、函数7.6相关模7.6objinobjnotins==ts!=ts<t非成员测试:objs中的一个元素吗?sts的元素都是t的成员sstt都是t的成员sststs合并操作:ersec- s&交集操作:st s- sts.symmetric_difference(t)s^ 对称差分操作:stst 操作:返回s的(浅)副本Table7.6集合类型,函数和方法(继续)s|=(Union)ersection_update(t)s&=t 交集修改操作:s中仅包括s和t中共有的成员s.difference_update(t)s-=t stobj,将丢弃操作:remove()的友好版 果 中存在 http:/ 练7–1.7–2.Python 同(b),但这次是根据已按照字母顺序排序好的字典的值,显示出这个字典中的键和值。(注意:对字典和哈希表来说,这样做一般没有什么实际意义,因为大多数和排序(如果需要)都是7- 建立字典。给定两个长度相同的列表,比如说,列表[1,2,3,...]和['abc',7–5.userpw2.py.下面的问题和例题7.1中管理名字-的键值对数据的程序有关修改那个,使它能记录用户上次的登录日期和时间(用time模块),并与用户一起4“Youalreadylog

温馨提示

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

评论

0/150

提交评论