翻譯:《實用的Python編程》01_07_Functions

目錄 | 上一節 (1.6 文件) | 下一節 (2.0 處理數據)python

1.7 函數

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

自定義函數

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

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

函數調用:segmentfault

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

練習

練習 1.29:定義一個函數

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

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

>>> greeting('Guido')
Hello Guido
>>> greeting('Paula')
Hello Paula
>>>

若是函數的第一條語句是字符串,那麼它被當作文檔字符串。嘗試輸入一個命令來顯示該文檔字符串,例如 help(greeting)

練習 1.30:將腳本轉換爲函數

把你在 練習1.27pcost.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.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 %

目錄 | 上一節 (1.6 文件) | 下一節 (2.0 處理數據) | 上一節 (1.6 文件) | 下一節 (2.0 處理數據))

注:完整翻譯見 https://github.com/codists/practical-python-zh

相關文章
相關標籤/搜索