简介
在这个实验中,你将学习如何回顾 Python 中简单函数的定义,并探索异常处理。函数是一个关键的编程概念,它能让你将代码组织成可重复使用的片段。而异常处理则是一种处理程序中错误和意外情况的方法。
本实验的主要目标是回顾定义简单函数的过程,并了解 Python 中的异常处理。需要修改的文件是 pcost.py
。
This tutorial is from open-source community. Access the source code
💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版
在这个实验中,你将学习如何回顾 Python 中简单函数的定义,并探索异常处理。函数是一个关键的编程概念,它能让你将代码组织成可重复使用的片段。而异常处理则是一种处理程序中错误和意外情况的方法。
本实验的主要目标是回顾定义简单函数的过程,并了解 Python 中的异常处理。需要修改的文件是 pcost.py
。
在这一步中,你将学习如何创建一个函数。Python 中的函数是一段组织有序、可重复使用的代码块,用于执行单个相关的操作。在这里,我们的函数将从文件中读取投资组合数据并计算总成本。这很有用,因为一旦我们有了这个函数,就可以多次使用它来处理不同的投资组合文件,避免反复编写相同的代码。
在之前的实验中,你可能已经编写了一些代码来读取投资组合数据并计算总成本。但这些代码可能编写方式不利于复用。现在,我们要将这些代码转换为一个可重复使用的函数。
投资组合数据文件有特定的格式。它们以 “股票代码 股数 价格” 的形式包含信息。文件中的每一行代表一项股票持仓。例如,在名为 portfolio.dat
的文件中,你可能会看到如下行:
AA 100 32.20
IBM 50 91.10
...
这里,第一部分(如 “AA” 或 “IBM”)是股票代码,它是股票的唯一标识符。第二部分是你持有的该股票的股数,第三部分是每股价格。
让我们在 /home/labex/project
目录下创建一个名为 pcost.py
的 Python 文件。这个文件将包含我们的函数。以下是我们要放在 pcost.py
文件中的代码:
def portfolio_cost(filename):
"""
计算投资组合文件的总成本(股数 * 价格)
参数:
filename: 投资组合文件的名称
返回:
投资组合的总成本,以浮点数表示
"""
total_cost = 0.0
## 打开文件并逐行读取
with open(filename, 'r') as f:
for line in f:
fields = line.split()
## 提取数据(股票代码、股数、价格)
shares = int(fields[1])
price = float(fields[2])
## 将成本累加到总成本中
total_cost += shares * price
return total_cost
## 使用 portfolio.dat 文件调用函数
if __name__ == '__main__':
cost = portfolio_cost('/home/labex/project/portfolio.dat')
print(cost)
在这段代码中,我们首先定义了一个名为 portfolio_cost
的函数,它接受一个 filename
作为参数。在函数内部,我们将变量 total_cost
初始化为 0.0。然后,我们使用 open
函数以只读模式('r'
)打开文件。我们使用 for
循环遍历文件中的每一行。对于每一行,我们使用 split()
方法将其拆分为多个字段。然后,我们提取股数并将其转换为整数,提取价格并将其转换为浮点数。我们通过将股数乘以价格来计算该股票持仓的成本,并将其添加到 total_cost
中。最后,我们返回 total_cost
。
if __name__ == '__main__':
部分用于在脚本直接运行时调用函数。我们将 portfolio.dat
文件的路径传递给函数,并打印结果。
现在,让我们运行程序,看看它是否能正常工作。我们需要导航到 pcost.py
文件所在的目录,然后运行 Python 脚本。以下是执行这些操作的命令:
cd /home/labex/project
python3 pcost.py
运行这些命令后,你应该会看到如下输出:
44671.15
这个输出表示投资组合中所有股票的总成本。
让我们逐步分析我们的函数所执行的操作:
filename
作为输入参数。这使我们能够使用该函数处理不同的投资组合文件。open
函数和 for
循环实现。split()
方法将其拆分为多个字段。该方法根据空白字符将行拆分为字符串列表。现在,这个函数是可重复使用的。我们可以使用不同的投资组合文件调用它来计算它们的成本,这使我们的代码更高效且更易于维护。
当你处理现实世界的数据时,遇到数据不一致或错误是非常常见的。例如,数据可能存在缺失值、格式不正确或其他问题。Python 提供了异常处理机制来优雅地处理这些情况。异常处理能让你的程序即使遇到错误也能继续运行,而不是突然崩溃。
让我们看一下 portfolio3.dat
文件。这个文件包含了一些投资组合的数据,如股票代码、股数和每股价格。要查看这个文件的内容,我们可以使用以下命令:
cat /home/labex/project/portfolio3.dat
当你运行这个命令时,你会注意到文件中的某些行在股数的位置使用了破折号 (-
) 而不是数字。以下是你可能看到的示例:
AA 100 32.20
IBM 50 91.10
C - 53.08
...
如果我们尝试在这个文件上运行当前的代码,程序将会崩溃。原因是我们的代码期望将股数转换为整数,但无法将破折号 (-
) 转换为整数。让我们尝试运行代码,看看会发生什么:
python3 -c "import sys; sys.path.append('/home/labex/project'); from pcost import portfolio_cost; print(portfolio_cost('/home/labex/project/portfolio3.dat'))"
你会看到类似这样的错误消息:
ValueError: invalid literal for int() with base 10: '-'
这个错误发生是因为 Python 在尝试执行 int(fields[1])
时,无法将 -
字符转换为整数。
Python 的异常处理使用 try
和 except
块。try
块包含可能引发异常的代码。异常是程序执行过程中发生的错误。except
块包含在 try
块中发生异常时将执行的代码。
以下是 try
和 except
块如何工作的示例:
try:
## 可能引发异常的代码
result = risky_operation()
except ExceptionType as e:
## 处理异常的代码
print(f"An error occurred: {e}")
当 Python 执行 try
块中的代码时,如果发生异常,执行会立即跳转到匹配的 except
块。except
块中的 ExceptionType
指定了我们要处理的异常类型。变量 e
包含有关异常的信息,如错误消息。
让我们更新 pcost.py
文件以处理数据中的错误。我们将使用 try
和 except
块跳过包含错误数据的行,并显示警告消息。
def portfolio_cost(filename):
"""
计算投资组合文件的总成本(股数 * 价格)
通过跳过包含错误数据的行并显示警告来处理这些行。
参数:
filename: 投资组合文件的名称
返回:
投资组合的总成本,以浮点数表示
"""
total_cost = 0.0
## 打开文件并逐行读取
with open(filename, 'r') as f:
for line in f:
fields = line.split()
try:
## 提取数据(股票代码、股数、价格)
shares = int(fields[1])
price = float(fields[2])
## 将成本累加到总成本中
total_cost += shares * price
except ValueError as e:
## 为无法解析的行打印警告
print(f"Couldn't parse: '{line}'")
print(f"Reason: {e}")
return total_cost
## 使用 portfolio3.dat 文件调用函数
if __name__ == '__main__':
cost = portfolio_cost('/home/labex/project/portfolio3.dat')
print(cost)
在这个更新后的代码中,我们首先打开文件并逐行读取。对于每一行,我们将其拆分为多个字段。然后,我们尝试将股数转换为整数,将价格转换为浮点数。如果这个转换失败(即发生 ValueError
),我们打印一条警告消息并跳过该行。否则,我们计算这些股票的成本并将其添加到总成本中。
现在,让我们使用有问题的文件运行更新后的程序。首先,我们需要导航到项目目录,然后运行 Python 脚本。
cd /home/labex/project
python3 pcost.py
你应该会看到如下输出:
Couldn't parse: 'C - 53.08
'
Reason: invalid literal for int() with base 10: '-'
Couldn't parse: 'DIS - 34.20
'
Reason: invalid literal for int() with base 10: '-'
44671.15
现在,程序会执行以下操作:
ValueError
。这种方法使我们的程序在处理不完美的数据时更加健壮。它可以优雅地处理错误并仍然提供有用的结果。
Python 提供了一种交互式模式,让你可以立即运行代码。这对于测试代码和尝试新功能非常有用。在这一步中,我们将学习如何直接从 Python 解释器调用函数。
要运行 Python 脚本并进入交互式模式,你可以使用 -i
标志。这个标志告诉 Python 在执行脚本后保持交互式状态。以下是具体操作方法:
cd /home/labex/project
python3 -i pcost.py
让我们来分析一下这个命令的作用:
cd /home/labex/project
将当前目录更改为 /home/labex/project
。这是我们的 pcost.py
脚本所在的位置。python3 -i pcost.py
执行 pcost.py
脚本。脚本运行完成后,Python 会保持在交互式模式。运行该命令后,你会看到 pcost.py
脚本的输出,随后是 Python 提示符 (>>>
)。这个提示符表示你现在可以输入 Python 命令了。
进入交互式模式后,你可以使用不同的文件名调用 portfolio_cost()
函数。这能让你了解该函数在不同输入下的行为。以下是一个示例:
>>> portfolio_cost('/home/labex/project/portfolio.dat')
44671.15
>>> portfolio_cost('/home/labex/project/portfolio2.dat')
19908.75
>>> portfolio_cost('/home/labex/project/portfolio3.dat')
Couldn't parse: 'C - 53.08
'
Reason: invalid literal for int() with base 10: '-'
Couldn't parse: 'DIS - 34.20
'
Reason: invalid literal for int() with base 10: '-'
44671.15
通过这种交互式方法,你可以:
交互式模式有几个优点:
当你完成实验后,可以通过两种方式退出交互式模式:
exit()
并按回车键。这是结束交互式会话的直接方法。在你的 Python 编程之旅中,定义函数并交互式测试它们的技术对于开发和调试将非常有价值。它能让你快速迭代代码,发现并修复问题。
在这个实验中,你学习了几个关键的 Python 编程概念。首先,你学会了如何定义和使用函数,这使你的代码可复用。其次,你掌握了实现异常处理,增强了程序的健壮性。最后,你了解了如何使用 Python 的交互式模式进行测试和实验。
这些技能是编写可靠 Python 程序的基础。函数有助于组织和复用代码,异常处理能让你优雅地处理意外情况,而交互式模式为测试和调试提供了强大的环境。随着你在 Python 学习道路上不断前进,这些概念在开发更大、更复杂的应用程序时将变得越来越有价值。