首頁>技術>

1.7 函式

隨著程式開始變大,我們會想要有條理地組織這些程式。本節簡要介紹函式、庫模組以及帶有異常的錯誤處理。

自定義函式

對你要重用的程式碼使用函式。下面是函式的定義方式:

def sumcount(n):    '''    Returns the sum of the first n integers    '''    total = 0    while n > 0:        total += n        n -= 1    return total

函式呼叫:

a = sumcount(100)

函式是執行某些任務並返回結果的一系列語句。 return 關鍵字需要顯式指定函式的返回值。

庫函式

Python 帶有一個大型的標準庫。使用 import 訪問庫模組。示例:

import mathx = math.sqrt(10)import urllib.requestu = urllib.request.urlopen('http://www.python.org/')data = u.read()

稍後,我們將更詳細地介紹庫和模組。

錯誤和異常

函式將錯誤報告為異常。異常會導致函式中止,如果未處理,可能會導致整個程式終止。

在你的 Python 直譯器(REPL)中嘗試一下:

>>> 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.pyTraceback (most recent call last):  File "foo.py", line 21, in <module>    raise RuntimeError("What a kerfuffle")RuntimeError: What a kerfuffle
練習練習 1.29:定義一個函式

嘗試定義一個簡單的函式:

>>> def greeting(name):        'Issues a greeting'        print('Hello', name)>>> greeting('Guido')Hello Guido>>> greeting('Paula')Hello Paula>>>

如果函式的第一條語句是字串,那麼它被當做文件字串。嘗試輸入一個命令來顯示該文件字串,例如 help(greeting)。

練習 1.30:將指令碼轉換為函式

把你在 練習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>>>

能夠互動地試驗程式碼對除錯和測試非常有用。

練習 1.31:錯誤處理

如果你在缺少某些欄位的檔案上使用函式,會發生什麼情況?

>>> 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 程式以捕獲異常,列印警告資訊然後繼續處理檔案餘下部分。

練習1.32:使用庫函式

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 模組進行解析,然後嘗試執行前面的示例。

練習 1.33:從命令列讀取

在 pcost.py 程式中,輸入檔案的名稱已經被硬編碼到程式碼中:

# pcost.pydef portfolio_cost(filename):    ...    # Your code here    ...cost = portfolio_cost('Data/portfolio.csv')print('Total cost:', cost)

雖然用於學習和測試還行,但在實際的程式中,你可能不會這麼做。

相反,你可以把檔名作為引數傳遞給指令碼。嘗試按以下步驟修改程式的底部:

# pcost.pyimport sysdef 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.csvTotal cost: 44671.15bash %

9
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 講解JDK從8以後(包含8)各個版本的各種新特性