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之旅才剛剛起步而已。