ImageVerifierCode 换一换
格式:DOCX , 页数:57 ,大小:43.29KB ,
资源ID:10549855      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/10549855.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(learnpython09.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

learnpython09.docx

1、learnpython09272第九章用Python完成常见的任务本章内容:数据结构操作文件操作操作程序与Internet相关的任务较大的例子练习现在,我们已学习了Python的语法,它的基本的数据类型,和很多我们喜欢的Python的库函数。本章假设你至少理解了这门语言的所有基本成分,并且除了Python的优雅和“酷”的方面外,也了解了它实用的方面。我们将介绍Python程序员要面对的常见的任务。这些任务分为数据结构操作,文件操作等等。数据结构操作Python的最大的特点之一是它把列表、元组和字典作为内置类型。它们非常灵活和容易使用,一旦你开始使用它们,你将发现你会不由自主地想到它们。内嵌 (

2、inline)拷贝由于Python引用的管理模式,语句a = b并没有对b引用的对象作拷贝,而只是对那个对象产生了新的引用。有时需要一个对象的新的拷贝,而不只是共享一个引用。怎样做到这一点依赖于对象的类型。拷贝列表和元组的最简单的方式有点奇怪。如果myList是一个列表,那么要对它做拷贝,你可以用:newList = myList:你可以理解为“从开始到结尾的分片”,因为我们在第二章“类型和操作符”里学用Python完成常见的任务273到,一个分片开始的缺省索引是序列的开始(0),而缺省的结尾是序列的结尾。由于元组支持同样的分片操作,这个技术也适用于拷贝元组。而字典却不支持分片操作。为了拷贝字

3、典myDict,你可以用:newDict=for key in myDict.keys(): newDictkey = myDictkey这个操作很常见,所以在Python 1.5里为字典对象增加了一个新方法来完成这个任务,就是copy()方法。所以前面的代码可以替换为一句话:newDict = myDict.copy()另一个常见的字典操作现在也是标准的字典特性了。如果你有一个字典oneDict,而想用另一个不同的字典otherDict的内容替换它,只需要用:oneDict.update(otherDict)这与下面的代码相同:for key in otherDict.keys(): one

4、Dictkey = otherDictkey如果在update()操作前oneDict与otherDict共享一些键时,在oneDict中的键关联的旧值将被删除掉。这也许是你所想要的(通常是这样,这也是为什么选择这个操作并称之为update()的原因)。如果这不是你期望的,那么要做的也许是抱怨(引发异常),如下:def mergeWithoutOverlap(oneDict, otherDict): newDict = oneDict.copy() for key in otherDict.keys(): if key in oneDict.keys(): raise ValueError,

5、the two dictionaries are sharing keys! newDictkey = otherDictkey return newDict或者把二者的值结合为一个元组,例如:def mergeWithOverlap(oneDict, otherDict): newDict = oneDict.copy()第九章274 for key in otherDict.keys(): if key in oneDict.keys(): newDictkey = oneDictkey, otherDictkey else: newDictkey = otherDictkey retur

6、n newDict为了说明前面三个算法的不同,考虑下面两个字典:phoneBook1 = michael: 555-1212, mark: 554-1121, emily: 556-0091phoneBook2 = latoya: 555-1255, emily: 667-1234如果phoneBook1可能是过时的,而phoneBook2更新一些但不够完整,那么正确的用法可能是phoneBooke1.update(phoneBook2)。如果认为两个电话本不应该有重复的键时,使用newBook = mergeWithoutOverlap(phoneBook1,phoneBook2)可以让你知

7、道假设是否有错。最后一种,如果一个是家里的电话本而另一个是办公室的电话本,那么只要是后续的引用newBookemily的代码能够处理newBookemily是元组(556-0091,667-1234)这一事实,就可以用:newBook = mergeWithoutOverlap(phoneBook1, phoneBook2)拷贝:copy模块回到拷贝主题上来::和.copy()技巧适用于90%的情况。如果你正按照Python的精神,编写可以处理任何参数类型的函数,有时需要拷贝X而不管X是什么。这时就需要copy模块。它提供了两个函数,copy和deepcopy。第一个就像序列的分片操作:或是字

8、典的copy方法。第二个函数更微妙并且与深度嵌套结构有关(这正是deepcopy的意思)。例如用分片操作:完整地拷贝listOne。这个技术产生了新的列表,如果原来的列表中的内容是不变的对象,如数字或字符串,这个拷贝就是“真正的”拷贝。然而假设listOne的第一项是一个字典(或任何其他容易变化的对象),那么listOne的拷贝的第一项只是对同一个字典的新的引用。所以如果你修改了那个字典,显然listOne和它的拷贝都修改了。用一个例子可以看得更清楚些:import copylistOne = name: Willie, city: Providence, RI, 1, tomato, 3.0

9、用Python完成常见的任务275listTwo = listOne: # or listTwo=copy.copy(listOne)listThree = copy.deepcopy(listOne) listOne.append(kid)listOne0city = San Francisco, CAprint listOne, listTwo, listThreename: Willie, city: San Francisco, CA, 1, tomato, 3.0, kidname: Willie, city:San Francisco, CA, 1, tomato, 3.0name

10、: Willie, city: Providence, RI, 1, tomato, 3.0正如你所见,直接修改listOne仅仅修改了listOne。对listOne的第一项的修改影响到listTwo,但没有影响listThree。这就是浅度拷贝(:)和深度拷贝的区别。copy模块的函数知道如何拷贝可以拷贝的内置函数(注1),包括类和实例。排序在第二章你知道列表有一个排序方法,有时你想要遍历整个排好序的列表而不想影响列表的内容。或者你也许想列出一个排好序的元组,而元组是不可变的,不允许有排序的方法。唯一的解决办法是拷贝一个列表,然后派序列表。例如:listCopy = list(myTupl

11、e)listCopy.sort()for item in listCopy: print item#或者做别的任何事情这也是处理那些没有内在顺序的数据结构的办法,例如字典。字典非常快的一个原因是实现时保留了改变键的顺序的权利。这其实不是一个问题,因为你可以拷贝字典的键然后遍历它:keys = myDict.keys()#返回字典的未排序的键keys.sort()for key in keys:#答应以键为序的健值对 print key, myDictkey列表的sort方法使用的是Python的标准比较方案。但有时你需要别的方案。例注1:有些对象是不可拷贝的,如模块、文件对象和套接字。记住,文

12、件对象与磁盘上的文件是不同的。第九章276如当你对一个单词列表排序时,大小写也许是没有意义的。而对字符串的标准比较中,所有大写字母都在小写之前,所以Baby小于apple而baby大于apple。为了进行大小写无关排序,你需要定义一个有两个参数的函数,并且根据第一个参数是小于,等于或大于第二个参数,分别返回-1,0,1。所以你可以这样写: def caseIndependentSort(something, other):. something, other = string.lower(something), string.lower(other). return cmp(something

13、, other). testList = this, is, A, sorted, ListtestList.sort()print testListA, List, is, sorted, thistestList.sort(caseIndependentSort)print testListA, is, List, sorted, this我们使用内置的函数cmp来完成比较工作。我们的排序函数只是把两项变成小写字母然后排序。也请注意小写转换是在比较函数局部范围内的,所以列表中的元素并没有因排序而修改。随机:random模块怎样随机排列一个序列呢?比如一个文本行的列表。最简单的办法是使用ra

14、ndom模块里的choice函数,它随机地返回序列的元素作为它的参数(注2)。为了避免重复地得到同样的行,记住删除已经选择了的项。当操作一个列表对象时,使用remove方法:while myList: #当myList空时停止循环 element = random.choice(myList) myList.remove(element) print element,如果你需要随机处理一个非列表对象,通常最简单的办法是把它转换为一个列表,注2:random模块提供了很多有用的函数,例如random函数,它返回一个介于0和1之间的随机浮点数。用Python完成常见的任务277然后对这个列表作随机

15、处理,而不是对每种数据类型都采用新的办法。这似乎是一个浪费的办法,也许要产生一个很巨大的列表。然而一般来说,对你似乎很大的数据,对于计算机来说可能不那么大,感谢Python的引用系统。而且不用对每种数据类型采用不同的方法,所节约的时间是很多的。Python的设计初衷就是要节约时间;如果那意味着运行一个稍慢一点或者大一点的程序,那就让它这样吧。如果你正在处理大量的数据,也许值得优化。但只有当确实需要优化时才去优化,否则将是浪费时间。定义新的数据结构对于数据结构来说,不要重复发明轮子这一原则尤其重要。例如,Python的列表和字典也许不是你习惯于使用的,但如果这些数据结构可以满足要求,你应当避免设

16、计自己的数据结构,它们使用的算法已经在各种情形下测试过,并且快而稳定。但有时这些算法的接口对某个特别的任务不方便。例如,计算机科学的教科书中经常用其他数据结构术语如队列、堆栈来描述算法。为了使用这些算法,定义与这些数据结构有同样方法的数据结构也许是有意义的。(比如堆栈的pop和push,或者队列的enqueue和dequeue)。而且,重用内置的列表类型来实现堆栈也是有意义的。换句话说,你需要行为像堆栈但却是基于列表的结构。最简单的办法是用一个类来包裹一个列表。为了最低限度地实现一个类,你可以这样写:class Stack: def _ _ init_ _ (self, data): self

17、._data = list(data) def push(self, item): self._data.append(item) def pop(self): item = self._data-1 del self._data-1 return item下面的语句不仅易写,易懂,而且易读,易用。thingsToDo = Stack(write to mom, invite friend over, wash thekid)第九章278thingsToDo.push(do the dishes) print thingsToDo.pop()do the dishesprint thingsT

18、oDo.pop()wash the kid在上面的堆栈类中用了两个标准的Python命名习惯,第一个是类名由大写字母开始,以便与函数名区别开。另一个是_data属性以一个下划线开始,这介于公共属性(不以下划线开始)和私有属性之间(以两个下划线开始,参见第六章“类”)。而Python的保留字在开始和结尾都有两个下划线。这里的意思是:_data是一个属性,用户不应该直接访问,类的设计者希望这个“伪私有”属性只被类和子类的方法使用。定义新的列表和字典:UserList和UserDict模块前面展示的堆栈类作了恰当的工作。它采取了关于堆栈的最小定义,只支持两个操作:p u s h和p o p。然而,

19、很快你就发现列表的特性确实好,比如可以用for.in.的方式访问所有的成员。这可以通过重用已有的代码来实现。在这里你应当应用UserList模块里定义的类UserList作为基类,堆栈由此派生而来。库里也包括UserDict模块,它是一个封装字典的类。一般来说,它们是用于特别子类的基类。#从UserList模块中导入UserList类from UserList import UserList#继承UserList类class Stack(UserList): push = UserList.append def pop(self): item = self-1 #使用_ _ getitem_

20、_ del self-1 return item这个堆栈是UserList的一个子类。UserList类通过定义特别的_ _ getitem_ _和_ _ delitem_ _方法实现了方括号的运算,所以前面代码里的pop能工作。你不必定义你自己的_ _ init_ _方法,因为UserList已经定义了一个相当不错的。最后只是说明push方法等于UserList的append方法。现在我们可以用列表和堆栈两种方式来操作了。用Python完成常见的任务279thingsToDo = Stack(write to mom, invite friend over, wash thekid)prin

21、t thingsToDo #从UserList继承write to mom, invite friend over, wash the kidthingsToDo.pop()wash the kidthingsToDo.push(change the oil) for chore in thingsToDo: #我们也可以用for .in .遍历内容. print chore #因为有_ _ getitem_ _.write to mominvite friend overchange the oil注意: 当我们写这本书时,Guido van Rossom宣布在Python 1.5.2(以及

22、后续版本里),列表对象将增加一个pop方法,它也有一个可选参数来指定pop的索引(缺省是列表最后的一个成员)。文件操作脚本语言的设计目标之一是帮助人们快速而简单地做重复工作。Web管理员,系统管理员和程序员的经常需要做的一件事是:从一个文件集合中选出一个子集,对这个子集做某种操作,并把结果写到一个或一组输出文件中(例如,在某个目录里的每个文件里,隔行查找以非#字符开头的行的最后一个词,并把它与文件名一起打印出来)。人们为这类任务已经设计了特定的工具,例如sed和awk。我们发现Python能很简单地完成这个工作。操作一个文本文件里的每一行当解析一个包含文本的输入文件时,sys模块是非常有用的。

23、在它的属性中有三个文件对象,分别称为sys.stdin、sys.stdout和sys.stderr。名字来源于三个流的概念: 分别为标准输入、标准输出和标准错误。它们与命令行工具有关,print语句使用标准输出。它是一个文件对象,具有以写模式打开的文件对象的所有输出方法,如write和writelines。另一个常用的流是标准输入(stdin),它也是一个文件对象,不过它拥有的是输入方法,例如read、readline和readlines。下面的脚本会算出通过“管道”输入的文件行数:第九章280import sysdata = sys.stdin.readlines()print Counte

24、d, len(data), lines.在Unix上你可以做如下的测试:%cat countlines.py | python countlines.pyCounted 3 lines.在Windows或DOS上,你可以:C:type countlines.py | python countlines.pyCounted 3 lines.当实现简单的过滤操作时,readlines函数是有用的。这里有一些过滤操作的例子:寻找所有以#开始的行import sysfor line in sys.stdin.readlines(): if line0 = #: print line,注意print语句

25、后的逗号是需要的,因为line字符串里已经有一个换行符。取出一个文件的第四列(这里列是由空白符定义的)import sys, stringfor line in sys.stdin.readlines(): words = string.split(line) if len(words) = 4: print words3我们通过words列表的长度判断是否确实至少有四个列,最后两行可以用try/except惯用法代替,这在Python里是常见的: try: print words3 except IndexError: #没有足够的列 pass取出文件的第四列,列由冒号分开,并用小写输出im

26、port sys, stringfor line in sys.stdin.readlines(): words = string.split(line, :)用Python完成常见的任务281 if len(words) = 4: print string.lower(words3)打印头10行,最后10行,并隔行打印输出import sys, stringlines = sys.stdin.readlines()sys.stdout.writelines(lines:10)#头10行sys.stdout.writelines(lines-10:)#最后10行for lineIndex in

27、 range(0, len(lines), 2):# 0, 2, 4, . sys.stdout.write(lineslineIndex)# 0, 2, 4, .行计算单词“Python”在一个文件里出现的次数import stringtext = open(fname).read()print string.count(text, Python)把一个文件的列变换为一个列表的行在这个比较复杂的例子里,任务是“转置”一个文件,设想你有这样一个文件:Name: Willie Mark Guido Mary Rachel AhmedLevel: 5 4 3 1 6 4Tag#: 1234 445

28、1 5515 5124 1881 5132而你希望它变成这样:Name: Level: Tag#:Willie 5 1234Mark 4 4451.你可以用下面的代码:import sys, stringlines = sys.stdin.readlines()wordlists = for line in lines: words = string.split(line) wordlists.append(words)for row in range(len(wordlists0): for col in range(len(wordlists): print wordlistscolrow

29、 + t, print当然你应当用更多的防卫性编程技巧来处理一些可能的情况,比如也许不是所有的行都有相同的单词数,也许丢失了数据等等。这些就作为练习留给读者。第九章282选择数据块的大小前面的所有例子都假设你能一次读入整个文件。然而有时候这是不可能的,比如在内存较小的计算机上处理大文件,或者处理不断地增加的文件(如日志文件)。对这种情况你可以用一个while/readline组合,一次读入文件的一小部分直到读完。对于不是基于行的文本文件,你必须一次读入一个字符:#逐字地读入while 1: next = sys.stdin.read(1)#读入一个单字符串 if not next:#或者读到EOF时是空串 break处理字符串next注意文件对象的read()方法在文件结尾时返回一个空串,并由此而跳出循环。然而更常见的是你将处理基于行的文本文件,并且一次处理一行:#逐行地读入while 1: next = sys.stdin.readline()#读入一个单行字符串 if not next:#或者读到EOF时是空串 break处理行next处理命令行上指定的一组文件能够读stdin是一个

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1