目錄 | 上一節 (1.6 文件) | 下一節 (2.0 處理數據)html
隨着程序開始變大,咱們會想要有條理地組織這些程序。本節簡要介紹函數、庫模塊以及帶有異常的錯誤處理。python
對你要重用的代碼使用函數。下面是函數的定義方式:git
def sumcount(n): ''' Returns the sum of the first n integers ''' total = 0 while n > 0: total += n n -= 1 return total
函數調用:github
a = sumcount(100)
函數是執行某些任務並返回結果的一系列語句。 return
關鍵字須要顯式指定函數的返回值。bash
Python 帶有一個大型的標準庫。使用 import
訪問庫模塊。示例:函數
import math x = math.sqrt(10) import urllib.request u = urllib.request.urlopen('http://www.python.org/') data = u.read()
稍後,咱們將更詳細地介紹庫和模塊。學習
函數將錯誤報告爲異常。異常會致使函數停止,若是未處理,可能會致使整個程序終止。測試
在你的 Python 解釋器(REPL)中嘗試一下:ui
>>> int('N/A') Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: invalid literal for int() with base 10: 'N/A' >>>
出於調試的目的,上面的錯誤信息描述了發生的狀況,錯誤產生的位置以及回溯。該回溯顯示致使失敗的其它函數調用。編碼
異常能夠被捕獲並處理。要捕獲異常,使用 try - except
語句:
for line in f: fields = line.split() try: shares = int(fields[1]) except ValueError: print("Couldn't parse", line) ...
該名稱 ValueError
必須與你嘗試捕獲的錯誤類型匹配。
一般,根據所執行的操做,很難提早確切地知道可能會發生哪一種錯誤。無論是好是壞,一般會添加在程序意外奔潰後的異常處理(示例:」天哪,咱們忘記捕獲錯誤了。咱們應該處理錯誤的。「)。
要觸發異常,請使用 raise
語句:
raise RuntimeError('What a kerfuffle')
這將致使程序因異常回溯而停止,除非該異常經過 try-except
代碼塊捕獲。
% python3 foo.py Traceback (most recent call last): File "foo.py", line 21, in <module> raise RuntimeError("What a kerfuffle") RuntimeError: What a kerfuffle
嘗試定義一個簡單的函數:
>>> def greeting(name): 'Issues a greeting' print('Hello', name) >>> greeting('Guido') Hello Guido >>> greeting('Paula') Hello Paula >>>
若是函數的第一條語句是字符串,那麼它被當作文檔字符串。嘗試輸入一個命令來顯示該文檔字符串,例如 help(greeting)
。
把你在 練習1.27 爲 pcost.py
程序編寫的代碼放到 portfolio_cost(filename)
函數裏面。此函數以文件名做爲輸入,讀取文件中的投資組合數據,把投資組合總的費用做爲浮點數返回。
要使用你的函數,請修改程序,使其看起來像下面這樣:
def portfolio_cost(filename): ... # Your code here ... cost = portfolio_cost('Data/portfolio.csv') print('Total cost:', cost)
運行程序時,你應該會看到和之前同樣的輸出。運行程序後,你也能夠輸入一下命令來交互式地調用函數:
bash $ python3 -i pcost.py
這將容許你從交互模式調用函數:
>>> portfolio_cost('Data/portfolio.csv') 44671.15 >>>
可以交互地試驗代碼對調試和測試很是有用。
若是你在缺乏某些字段的文件上使用函數,會發生什麼狀況?
>>> portfolio_cost('Data/missing.csv') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "pcost.py", line 11, in portfolio_cost nshares = int(fields[1]) ValueError: invalid literal for int() with base 10: '' >>>
在這一點上,你面臨一個決定:要使程序正常工做,你能夠經過消除錯誤行(bad lines)來清理原始輸入文件,或者修改代碼,以某種方式處理錯誤行。
請修改 pcost.py
程序以捕獲異常,打印警告信息而後繼續處理文件餘下部分。
Python 帶有一個擁有大量有用函數的大型標準庫。csv
模塊是一個在這裏可能有用的庫。不管什麼時候,每當必須必須使用 CSV 數據文件時,都應使用 csv
模塊。下面是一個有關 csv
模塊是如何工做的示例:
>>> import csv >>> f = open('Data/portfolio.csv') >>> rows = csv.reader(f) >>> headers = next(rows) >>> headers ['name', 'shares', 'price'] >>> for row in rows: print(row) ['AA', '100', '32.20'] ['IBM', '50', '91.10'] ['CAT', '150', '83.44'] ['MSFT', '200', '51.23'] ['GE', '95', '40.37'] ['MSFT', '50', '65.10'] ['IBM', '100', '70.44'] >>> f.close() >>>
csv
模塊有一個很是棒的功能——它處理各類底層細節,例如引號和適當的逗號拆分。在上面的輸出中,你會注意到它從第一列的名稱(names)中刪除了雙引號。
修改你的 pcost.py
程序,以使用 csv
模塊進行解析,而後嘗試運行前面的示例。
在 pcost.py
程序中,輸入文件的名稱已經被硬編碼到代碼中:
# pcost.py def portfolio_cost(filename): ... # Your code here ... cost = portfolio_cost('Data/portfolio.csv') print('Total cost:', cost)
雖然用於學習和測試還行,但在實際的程序中,你可能不會這麼作。
相反,你能夠把文件名做爲參數傳遞給腳本。嘗試按如下步驟修改程序的底部:
# pcost.py import sys def portfolio_cost(filename): ... # Your code here ... if len(sys.argv) == 2: filename = sys.argv[1] else: filename = 'Data/portfolio.csv' cost = portfolio_cost(filename) print('Total cost:', cost)
sys.argv
是一個列表,該列表包含了在命令行上傳遞的參數(若是有)。
要運行程序,你須要從終端(terminal)運行 Python。
示例,從 Unix系統中的 bash 運行:
bash % python3 pcost.py Data/portfolio.csv Total cost: 44671.15 bash %