Python from entry to abandon 4
Python from entry to abandon系列的收官之作
本篇博客将会介绍《简明Python教程》的最后四章内容。并在最后附上对于本书的个人评价和下阶段自学Python系列博客更新的计划。
13.异常
14.Python标准库
15.更多Python内容
16.接下来学习什么?
13.异常
当你的程序中出现某些异常的状况的时候,异常就发生了。例如,当你想要读某个文件的时 候,而那个文件不存在。或者在程序运行的时候,你不小心把它删除了。上述这些情况可以使用异常来处理。
笔记:简单理解就是程序没有正常执行(例如编辑器报错)就是异常。
假如你的程序中有一些无效的语句,会怎么样呢?Python会引发并告诉你那里有一个错误,从 而处理这样的情况。
13.1错误
考虑一个简单的print语句。假如我们把print误拼为Print,注意大写,这样Python会引发 一个语 法错误。
示例
>>> Print 'Hello World' File "<stdin>", line 1 Print 'Hello World' ^ SyntaxError: invalid syntax >>> print 'Hello World' Hello World
我们可以观察到有一个SyntaxError被引发,并且检测到的错误位置也被打印了出来。这是这个 错误的 错误处理器 所做的工作。
我们尝试读取用户的一段输入。按Ctrl-d,看一下会发生什么。
示例
>>> s=raw_input('Enter something-->') Enter something-->Traceback (most recent call last): File "<stdin>", line 1, in <module> EOFError
Python引发了一个称为EOFError的错误,这个错误基本上意味着它发现一个不期望的 文件尾 (由Ctrl-d表示)
13.2处理异常
我们可以使用try..except语句来处理异常。我们把通常的语句放在try-块中,而把我们的错误处 理语句放在except-块中。
例13.1
#!/usr/bin/Python #Filename:try_except.py import sys try: s=raw_input('Enter something-->') except EOFError: print 'Why did you do an EOF on me?' sys.exit() except: print '\nSome error/exception occurred' print 'Done'
输出:
# Python try_except.py Enter something-->Why did you do an EOF on me? # Python try_except.py Enter something-->Python is exceptional! Done
如何工作:
我们把所有可能引发错误的语句放在try块中,然后在except从句/块中处理所有的错误和异常。 except从句可以专门处理单一的错误或异常,或者一组包括在圆括号内的错误/异常。如果没有 给出错误或异常的名称,它会处理 所有的 错误和异常。对于每个try从句,至少都有一个相关 联的except从句。
如果某个错误或异常没有被处理,默认的Python处理器就会被调用。它会终止程序的运行,并 且打印一个消息,我们已经看到了这样的处理。
你还可以让try..catch块关联上一个else从句。当没有异常发生的时候,else从句将被执行。
我们还可以得到异常对象,从而获取更多有个这个异常的信息。
笔记:
让try..catch块关联上一个else从句
示例
#!/usr/bin/Python #Filename:lansou.py try: s=raw_input('Enter an number-->') except EOFError: print '\nlansou' else: print 'xianggu'
程序不发生EOFError错误时就会只执行print’xianggu’,
不过直接把else:去掉效果其实是一样的。
13.3引发异常:
你可以使用raise语句 引发 异常。你还得指明错误/异常的名称和伴随异常 触发的 异常对象。你 可以引发的错误或异常应该分别是一个Error或Exception类的直接或间接导出类。
笔记:可以自定义错误/异常的类型,满足特定条件后用raise引发异常,
将自定义的异常跟在except之后,就能用来处理自定义的错误/异常类型了。
如何引发异常
例13.2
#!/usr/bin/Python #Filename:raising.py class ShortInputException(Exception): def __init__(self,length,atleast): Exception.__init__(self) self.length=length self.atleast=atleast try: s=raw_input('Enter something-->') if len(s)<3: raise ShortInputException(len(s),3) except EOFError: print '\nWhy did you do an EOF on me?' except ShortInputException,x: print 'ShortInputException:The input was of length %d,\ was expecting at least %d'%(x.length,x.atleast) else: print 'No exception was raised.'
输出:
# Python raising.py Enter something--> Why did you do an EOF on me? # Python raising.py Enter something-->ab ShortInputException:The input was of length 2, was expecting at least 3 # Python raising.py Enter something-->abc No exception was raised.
如何工作:
这里,我们创建了我们自己的异常类型,其实我们可以使用任何预定义的异常/错误。这个新 的异常类型是ShortInputException类。它有两个域——length是给定输入的长度,atleast则是程序 期望的最小长度。
在except从句中,我们提供了错误类和用来表示错误/异常对象的变量。这与函数调用中的形参和实参概念类似。在这个特别的except从句中,我们使用异常对象的length和atleast域来为用户打印一个恰当的消息。
笔记:这段程序相当综合,涉及类,继承,条件判断,raise语句,except从句中变量替换,else从句等等。背熟了自己码一遍————嗯,简直强无敌。这里我发现一个问题,在except ShortInputException,x:中,为什么x是必须的,为什么不能去掉x用ShortInputException直接引用length和atleast?
13.4try..finally语句
假如你在读一个文件的时候,希望在无论异常发生与否的情况下都关闭文件,该怎么做呢?这 可以使用finally块来完成。注意,在一个try块下,你可以同时使用except从句和finally块。如果 你要同时使用它们的话,需要把一个嵌入另外一个。
使用finally
例13.3
#!/usr/bin/Python #Filename:finally.py import time try: f=file('poem.txt') while True: line=f.readline() if len(line)==0: break time.sleep(2) print line, finally: f.close() print 'Cleaning up...closed the file'
输出:
# Python finally.py Programming is fun When the work is done if you wanna make you work also fun: use Python! Cleaning up...closed the file # Python finally.py Programming is fun When the work is done ^CCleaning up...closed the file Traceback (most recent call last): File "finally.py", line 12, in <module> time.sleep(2) KeyboardInterrupt
如何工作:
我们进行通常的读文件工作,但是我有意在每打印一行之前用time.sleep方法暂停2秒钟。这样 做的原因是让程序运行得慢一些(Python由于其本质通常运行得很快)。在程序运行的时候, 按Ctrl-c中断/取消程序。
我们可以观察到KeyboardInterrupt异常被触发,程序退出。但是在程序退出之前,finally从句仍 然被执行,把文件关闭。
笔记:学到了time模块的sleep函数,有趣。
概括:
我们已经讨论了try..except和try..finally语句的用法。我们还学习了如何创建我们自己的异常类型 和如何引发异常。
接下来,我们将探索Python标准库。
14.Python标准库
14.1简介
Python标准库是随Python附带安装的,它包含大量极其有用的模块。熟悉Python标准库是十分 重要的,因为如果你熟悉这些库中的模块,那么你的大多数问题都可以简单快捷地使用它们来解决。
我们已经研究了一些这个库中的常用模块。你可以在Python附带安装的文档的“库参考”一节 中了解Python标准库中所有模块的完整内容。
14.2 sys模块
命令行参数sys.argv
例14.1
#!/usr/bin/Python #Filename:cat.py import sys def readfile(filename): '''Print a file to the standard output.''' f=file(filename) while True: line=f.readline() if len(line)==0: break print line, f.close() #Script starts from here if len(sys.argv)<2: print 'No action specified.' sys.exit() if sys.argv[1].startswith('--'): option=sys.argv[1][2:] if option=='version': print 'Version 1.2' elif option=='help': print '''\ This program prints files to the standard output. Any number of files can be specified. Options include: --version:Prints the version number --help:Display this help''' else: print 'Unknown option.' sys.exit() else: for filename in sys.argv[1:]: readfile(filename)
输出:
# Python cat.py No action specified. # Python cat.py --help This program prints files to the standard output. Any number of files can be specified. Options include: --version:Prints the version number --help:Display this help # Python cat.py --version Version 1.2 # Python cat.py --nonsense Unknown option. # Python cat.py poem.txt Programming is fun When the work is done if you wanna make you work also fun: use Python!
如何工作:
这个程序用来模范Linux/Unix用户熟悉的cat命令。你只需要指明某些文本文件的名字,这个程 序会把它们打印输出。
在Python程序运行的时候,即不是在交互模式下,在sys.argv列表中总是至少有一个项目。它就是当前运行的程序名称,作为sys.argv[0](由于Python从0开始计数)。其他的命令行参数在这 个项目之后。
为了使这个程序对用户更加友好,我们提供了一些用户可以指定的选项来了解更多程序的内容。我们使用第一个参数来检验我们的程序是否被指定了选项。如果使用了–version选项,程序的版本号将被打印出来。类似地,如果指定了–help选项,我们提供一些关于程序的解释。 我们使用sys.exit函数退出正在运行的程序。和以往一样,你可以看一下help(sys.exit)来了解更多 详情。
如果没有指定任何选项,而是为程序提供文件名的话,它就简单地打印出每个文件地每一行,按照命令行中的顺序一个文件接着一个文件地打印。
顺便说一下,名称cat是concatenate的缩写,它基本上表明了程序的功能——它可以在输出打印一个文件或者把两个或两个以上文件连接/级连在一起打印。
更多sys的内容
sys.version 提供安装的Python的版本信息。
sys.version_info 是一个元祖,提供Python版本信息
sys.stdin标准输入相关
sys.stdout标准输出相关
sys.error标准错误流
在命令行模式可以看到他们的用处,这里不一一列举。
14.3 os模块
这个模块包含普遍的操作系统功能。如果你希望你的程序能够与平台无关的话,这个模块是尤 为重要的。即它允许一个程序在编写后不需要任何改动,也不会发生任何问题,就可以在 Linux和Windows下运行。一个例子就是使用os.sep可以取代操作系统特定的路径分割符。
下面列出了一些在os模块中比较有用的部分。它们中的大多数都简单明了。
os.name字符串指示你正在使用的平台。比如对于Windows,它是’nt’,而对于Linux/Unix 用户,它是’posix’。
os.getcwd()函数得到当前工作目录,即当前Python脚本工作的目录路径。
os.getenv()和os.putenv()函数分别用来读取和设置环境变量。
os.listdir()返回指定目录下的所有文件和目录名。
os.remove()函数用来删除一个文件。
os.linesep字符串给出当前平台使用的行终止符。例如,Windows使用’\r\n’,Linux使 用’\n’而Mac使用’\r’。
os.path.split()函数返回一个路径的目录名和文件名。
>>> os.path.split('/home/swaroop/byte/code/poem.txt') ('/home/swaroop/byte/code', 'poem.txt')
os.path.isfile()和os.path.isdir()函数分别检验给出的路径是一个文件还是目录。类似地,os. path.exists()函数用来检验给出的路径是否真地存在。
你可以利用Python标准文档去探索更多有关这些函数和变量的详细知识。你也可以使用help (sys)等等。
概括:
14章介绍了Python标准库中sys和os模块的一部分功能。利用Python标准文档可以学习这两个模块以及其他模块的更多内容。
15.更多Python的内容
到目前为止,我们已经学习了绝大多数常用的Python知识。在这一章中,我们将要学习另外一 些方面的Python知识,从而使我们对Python的了解更加 完整 。
15.1特殊的方法
在类中有一些特殊的方法具有特殊的意义,比如init和del方法,它们的重要性我们已 经学习过了。
一般说来,特殊的方法都被用来模仿某个行为。例如,如果你想要为你的类使用x[key]这样的 索引操作(就像列表和元组一样),那么你只需要实现getitem()方法就可以了。想一下, Python就是对list类这样做的!
笔记:特殊方法就是前后各有双下划线的类内部定义的方法。这本书详细介绍了init del的用法,其他我觉得没有列出来的必要,不知道用法记住也没有多大意义。
15.2单语句块
现在,你已经很深刻地理解了每一个语句块是通过它的缩进层次与其它块区分开来的。然而这 在大多数情况下是正确的,但是并非100%的准确。如果你的语句块只包含一句语句,那么你 可以在条件语句或循环语句的同一行指明它。下面这个例子清晰地说明了这一点:
>>> flag = True >>> if flag: print 'Yes' ... Yes
就如你所看见的,单个语句被直接使用而不是作为一个独立的块使用。虽然这样做可以使你的 程序变得 小一些 ,但是除了检验错误之外我强烈建议你不要使用这种缩略方法。不使用它的 一个主要的理由是一旦你使用了恰当的缩进,你就可以很方便地添加一个额外的语句。
另外,注意在使用交互模式的Python解释器的时候,它会通过恰当地改变提示符来帮助你输入 语句。在上面这个例子中,当你输入了关键字if之后,Python解释器把提示符改变为…以表示语 句还没有结束。在这种情况下,我们按回车键用来确认语句已经完整了。然后,Python完成整 个语句的执行,并且返回原来的提示符并且等待下一句输入。
15.3列表综合
通过列表综合,可以从一个已有的列表导出一个新的列表。例如,你有一个数的列表,而你想要得到一个对应的列表,使其中所有大于2的数都是原来的2倍。对于这种应用,列表综合是最 理想的方法。
使用列表综合
例15.1
#!/usr/bin/Python #Filename:list_comprehension.py listone=[2,3,4] listtwo=[2*i for i in listone if i>2] print listtwo
输出:
# Python list_comprehension.py [6, 8]
如何工作:
这里我们为满足条件(if i > 2)的数指定了一个操作(2i),从而导出一个新的列表。注意原 来的列表并没有发生变化。在很多时候,我们都是使用循环来处理列表中的每一个元素,而使 用列表综合可以用一种更加精确、简洁、清楚的方法完成相同的工作。
15.4在函数中接收元组和列表
当要使函数接收元组或字典形式的参数的时候,有一种特殊的方法,它分别使用和**前缀。 这种方法在函数需要获取可变数量的参数的时候特别有用。
>>> def powersum(power, *args): ... '''Return the sum of each argument raised to specified power.''' ... total = 0 ... for i in args: ... total += pow(i, power) ... return total ... >>> powersum(2, 3, 4) 25 >>> powersum(2, 10) 100
由于在args变量前有*前缀,所有多余的函数参数都会作为一个元组存储在args中。如果使用的 是**前缀,多余的参数则会被认为是一个字典的键/值对。
笔记:
自己看了一遍去编写,一万种错法。果然眼高手低。
注意,以下是各种神奇(逗比)的错误方式,真的好玩。
>>> def powersum(pow,*args): ... total=0 ... if i in args: ... total+=power(i,pow) ... return total ... >>> powersum(2,3,4) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in powersum NameError: global name 'i' is not defined >>> def powersum(pow,*args) File "<stdin>", line 1 def powersum(pow,*args) ^ SyntaxError: invalid syntax >>> def powersum(pow,*args): ... total=0 ... for i in args: ... total+=power(i,pow) ... return total ... >>> powernum(2,3,4) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'powernum' is not defined >>> powersum(2,3,4) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in powersum NameError: global name 'power' is not defined
15.5 lambda语句
lambda语句用来创建新的函数对象,并且在运行时返回它们(需要和return语句搭配使用)。
使用lambda形式
例15.2
#!/usr/bin/Python #Filename:lambda.py def make_repeater(n): return lambda s:s*n twice=make_repeater(2) print twice('word') print twice(5)
输出:
# Python lambda.py wordword 10
如何工作:
它如何工作
这里,我们使用了make_repeater函数在运行时创建新的函数对象,并且返回它。lambda语句用 来创建函数对象。本质上,lambda需要一个参数,后面仅跟单个表达式作为函数体,而表达式 的值被这个新建的函数返回。注意,即便是print语句也不能用在lambda形式中,只能使用表达式。
15.6 exec和eval语句
exec语句用来执行储存在字符串或文件中的Python语句。
>>> exec 'print "Hello World"' Hello World
eval语句用来计算储存在在字符串中的有效Python表达式。
>>> eval('2*3') 6
笔记:注意eval语句的格式和exec不同。
15.7 assert语句
assert语句用来声明某个条件是真的。例如,如果你非常确信某个你使用的列表中至少有一个 元素,而你想要检验这一点,并且在它非真的时候引发一个错误,那么assert语句是应用在这 种情形下的理想语句。当assert语句失败的时候,会引发一个AssertionError。
笔记:这里让我想起了老师曾经说过的运维一定要三思而后行。纯靠记忆显然是不靠谱的,要用实践来进行检验。
>>> mylist=['item'] >>> assert len(mylist)>=1 >>> mylist.pop() 'item' >>> assert len(mylist)>=1 Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError
笔记:这里mylist.pop()执行的功能是从队列的尾部推出一个元素。
>>> mylist=['apple','banana'] >>> mylist.pop() 'banana' >>> mylist.pop() 'apple'
15.8 repr函数
repr函数用来取得对象的规范字符串表示。反引号(也称转换符)可以完成相同的功能。
注意,在大多数时候有eval(repr(object)) == object。
>>> i=[] >>> i.append('item') >>> `i` "['item']" >>> repr(i) "['item']"
基本上,repr函数和反引号用来获取对象的可打印的表示形式。你可以通过定义类的repr 方法来控制你的对象在被repr函数调用的时候返回的内容。
笔记:
>>> print i ['item'] >>> print repr(i) ['item'] >>> repr(i) "['item']"
以上示例可以更好的说明什么叫做获取对象的可打印的表示形式。
概括
在这一章中,我们又学习了一些Python的特色,然而你可以肯定我们并没有学习完Python的所 有特色。不过,到目前为止,我们确实已经学习了绝大多数你在实际中会使用的内容。这些已 经足以让你去创建任何程序了。
接下来,我们会讨论一下如何进一步深入探索Python。
16.接下来学习什么?
16.1图形软件(GUI工具概括)
这一部分我不打算列出来,因为我对图形软件没好感。
16.2探索更多内容
Python标准库是一个丰富的库,在大多数时候,你可以在这个库中找到你所需的东西。 这被称为Python的“功能齐全”理念。我强烈建议你在开始开发大型Python程序之前浏 览一下Python标准文档。
Python.org——Python编程语言的官方主页。你可以在上面找到Python语言和解释器的最 新版本。另外还有各种邮件列表活跃地讨论Python的各方面内容。
comp.lang.Python是讨论Python语言的世界性新闻组。你可以把你的疑惑和询问贴在这个 新闻组上。可以使用Google群在线访问这个新闻组,或加入作为新闻组镜像的邮件列 表。
《Python实用大全》是一个极有价值的秘诀和技巧集合,它帮助你解决某些使用Python 的问题。这是每个Python用户必读的一本书。
《迷人的Python》是David Mertz编著的一系列优秀的Python相关文章。
《深入理解Python》是给有经验的Python程序员的一本很优秀的书。如果你已经完整地 阅读了本书,那么我强烈建议你接下来阅读《深入理解Python》。它覆盖了包括XML处 理、单元测试和功能性编程在内的广泛的主题。
Jython是用Java语言实现的Python解释器。这意味着你可以用Python语言编写程序而同时 使用Java库!Jython是一个稳定成熟的软件。如果你也是一个Java程序员,我强烈建议你 尝试一下Jython。
IronPython是用C#语言实现的Python解释器,可以运行在.NET、Mono和DotGNU平台 上。这意味着你可以用Python语言编写程序而使用.NET库以及其他由这三种平台提供的 库!IronPython还只是一个前期alpha测试软件,现在还只适合用来进行试验。Jim Hugunin,IronPython的开发者,已经加入了微软公司,将在将来全力开发一个完整版本 的IronPython。
Lython是Python语言的Lisp前段。它类似于普通的Lisp语言,会被直接编译为Python字节 码,这意味着它能与我们普通的Python代码协同工作。
另外还有很多很多的Python资源。其中比较有趣的有Daily Python-URL!,它使你保持与 Python的最新进展同步。另外还有Vaults of Parnassus、ONLamp.com Python DevCenter、 dirtSimple.org、Python Notes等等。
概括
现在,我们已经来到了本书的末尾,但是就如那句名言,这只是 开始的结束 !你现在是一个 满怀渴望的Python用户,毫无疑问你准备用Python解决许多问题。你可以使你的计算机自动地 完成许多先前无法想象的工作或者编写你自己的游戏,以及更多别的什么东西。所以,请出发吧!
结尾笔记:
很开心,看完了第一本Python相关书籍。
按照书中的流程走了一遍,结合笔记和知识点总结成了这四篇博客。在整个过程中,书中给出的例题大多数凭记忆敲了一遍,看了一遍书之后写博客的时候相当于把书又读了一遍,甚至比单独看书的时候还要认真。自我感觉这是一个不错的学习方法,对巩固知识点很有帮助,相当于复习和总结。
借用书中提到的丘吉尔的名言,“Now this is not the end.It is not even the beginning of the end.But it is,perhaps,the end of the beginning.”
是的,精彩的Python之旅才刚刚起步而已。