回顾简单函数的异常处理

PythonPythonBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在这个实验中,你将学习如何回顾 Python 中简单函数的定义,并探索异常处理。函数是一个关键的编程概念,它能让你将代码组织成可重复使用的片段。而异常处理则是一种处理程序中错误和意外情况的方法。

本实验的主要目标是回顾定义简单函数的过程,并了解 Python 中的异常处理。需要修改的文件是 pcost.py


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/BasicConceptsGroup(["Basic Concepts"]) python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/ErrorandExceptionHandlingGroup(["Error and Exception Handling"]) python(("Python")) -.-> python/FileHandlingGroup(["File Handling"]) python/BasicConceptsGroup -.-> python/python_shell("Python Shell") python/FunctionsGroup -.-> python/function_definition("Function Definition") python/ErrorandExceptionHandlingGroup -.-> python/catching_exceptions("Catching Exceptions") python/FileHandlingGroup -.-> python/file_opening_closing("Opening and Closing Files") python/FileHandlingGroup -.-> python/file_reading_writing("Reading and Writing Files") subgraph Lab Skills python/python_shell -.-> lab-132393{{"回顾简单函数的异常处理"}} python/function_definition -.-> lab-132393{{"回顾简单函数的异常处理"}} python/catching_exceptions -.-> lab-132393{{"回顾简单函数的异常处理"}} python/file_opening_closing -.-> lab-132393{{"回顾简单函数的异常处理"}} python/file_reading_writing -.-> lab-132393{{"回顾简单函数的异常处理"}} end

定义函数

在这一步中,你将学习如何创建一个函数。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

这个输出表示投资组合中所有股票的总成本。

理解代码

让我们逐步分析我们的函数所执行的操作:

  1. 它接受一个 filename 作为输入参数。这使我们能够使用该函数处理不同的投资组合文件。
  2. 它打开文件并逐行读取。这通过 open 函数和 for 循环实现。
  3. 对于每一行,它使用 split() 方法将其拆分为多个字段。该方法根据空白字符将行拆分为字符串列表。
  4. 它将股数转换为整数,将价格转换为浮点数。这是必要的,因为从文件中读取的数据是字符串格式,而我们需要对它们进行算术运算。
  5. 它计算每一项股票持仓的成本(股数 * 价格),并将其累加到总成本中。这使我们得到投资组合的总成本。
  6. 它返回最终的总成本。这使我们可以在程序的其他部分使用该结果(如果需要)。

现在,这个函数是可重复使用的。我们可以使用不同的投资组合文件调用它来计算它们的成本,这使我们的代码更高效且更易于维护。

✨ 查看解决方案并练习

添加错误处理

当你处理现实世界的数据时,遇到数据不一致或错误是非常常见的。例如,数据可能存在缺失值、格式不正确或其他问题。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 的异常处理使用 tryexcept 块。try 块包含可能引发异常的代码。异常是程序执行过程中发生的错误。except 块包含在 try 块中发生异常时将执行的代码。

以下是 tryexcept 块如何工作的示例:

try:
    ## 可能引发异常的代码
    result = risky_operation()
except ExceptionType as e:
    ## 处理异常的代码
    print(f"An error occurred: {e}")

当 Python 执行 try 块中的代码时,如果发生异常,执行会立即跳转到匹配的 except 块。except 块中的 ExceptionType 指定了我们要处理的异常类型。变量 e 包含有关异常的信息,如错误消息。

使用异常处理修改函数

让我们更新 pcost.py 文件以处理数据中的错误。我们将使用 tryexcept 块跳过包含错误数据的行,并显示警告消息。

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

现在,程序会执行以下操作:

  1. 尝试处理文件的每一行。
  2. 如果某行包含无效数据,捕获 ValueError
  3. 打印有关问题的有用消息。
  4. 继续处理文件的其余部分。
  5. 根据有效行返回总成本。

这种方法使我们的程序在处理不完美的数据时更加健壮。它可以优雅地处理错误并仍然提供有用的结果。

✨ 查看解决方案并练习

交互式实验

Python 提供了一种交互式模式,让你可以立即运行代码。这对于测试代码和尝试新功能非常有用。在这一步中,我们将学习如何直接从 Python 解释器调用函数。

以交互式模式运行 Python

要运行 Python 脚本并进入交互式模式,你可以使用 -i 标志。这个标志告诉 Python 在执行脚本后保持交互式状态。以下是具体操作方法:

cd /home/labex/project
python3 -i pcost.py

让我们来分析一下这个命令的作用:

  1. 首先,cd /home/labex/project 将当前目录更改为 /home/labex/project。这是我们的 pcost.py 脚本所在的位置。
  2. 然后,python3 -i pcost.py 执行 pcost.py 脚本。脚本运行完成后,Python 会保持在交互式模式。
  3. 在交互式模式下,你可以直接在终端中输入 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

通过这种交互式方法,你可以:

  • 使用不同的输入测试函数,查看其是否按预期工作。
  • 试验函数在各种条件下的行为。
  • 通过查看函数调用的即时结果,即时调试代码。

交互式模式的优点

交互式模式有几个优点:

  1. 你可以快速测试不同的场景,而无需每次都运行整个脚本。
  2. 你可以立即检查变量和表达式的结果,这有助于你理解代码的运行情况。
  3. 你可以测试小段代码,而无需创建完整的程序。这对于学习和尝试新想法非常有用。
  4. 这是学习和试验 Python 的绝佳方式,因为你能得到即时反馈。

退出交互式模式

当你完成实验后,可以通过两种方式退出交互式模式:

  • 输入 exit() 并按回车键。这是结束交互式会话的直接方法。
  • 按 Ctrl+D(在 Unix/Linux 系统上)。这是一个快捷键,也可以退出交互式模式。

在你的 Python 编程之旅中,定义函数并交互式测试它们的技术对于开发和调试将非常有价值。它能让你快速迭代代码,发现并修复问题。

✨ 查看解决方案并练习

总结

在这个实验中,你学习了几个关键的 Python 编程概念。首先,你学会了如何定义和使用函数,这使你的代码可复用。其次,你掌握了实现异常处理,增强了程序的健壮性。最后,你了解了如何使用 Python 的交互式模式进行测试和实验。

这些技能是编写可靠 Python 程序的基础。函数有助于组织和复用代码,异常处理能让你优雅地处理意外情况,而交互式模式为测试和调试提供了强大的环境。随着你在 Python 学习道路上不断前进,这些概念在开发更大、更复杂的应用程序时将变得越来越有价值。