目录 | 上一节 (1.6 文件) | 下一节 (2.0 解决数据)
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 %
目录 | 上一节 (1.6 文件) | 下一节 (2.0 解决数据)
注:残缺翻译见 https://github.com/codists/practical-python-zh