likes
comments
collection
share

【Python基础】异常处理机制什么是异常? 在编程中,异常是指在程序执行过程中发生的意外情况,这些情况会导致程序无法正

作者站长头像
站长
· 阅读数 45

什么是异常?

在编程中,异常是指在程序执行过程中发生的意外情况,这些情况会导致程序无法正常运行。例如,当你试图除以零或访问不存在的文件时,就会引发异常。Python 提供了一套丰富的内置异常,用于处理各种错误情况。

Python 内置 的异常
  • ZeroDivisionError:除以零。
  • ImportError:导入模块或包失败。
  • IndexError:访问列表、元组或其他序列类型的索引超出了范围。
  • NameError:访问一个未定义的变量。
  • SyntaxError:语法错误。
  • TypeError:当传递给函数的参数类型不符合函数预期。
  • ValueError:当传递给函数的参数值不符合预期,但类型正确时抛出。
  • KeyError:当尝试从字典中获取一个不存在的键时抛出。
  • OSError:操作系统相关的错误,如文件操作失败。

异常处理的基本结构

Python 的异常处理机制主要由 tryexceptelsefinally 关键字组成。这些关键字帮助程序在遇到错误时采取适当的行动,而不是让程序崩溃。

  • try:块内包含可能引发异常的代码块,也就是你写的代码咯。
  • except:捕获并处理特定类型的异常。可用多个 except 块来处理不同类型的异常。
  • else:如果 try 块没有抛出任何异常,则执行这里的代码。
  • finally:无论是否发生异常,都会执行这里的代码,通常用于清理工作。
示例
try:
    num1 = 5
    num2 = 2
    result = num1 / num2
except ZeroDivisionError as e:
    print(f"发生错误: {e}")
    print("错误为:分母为0")
else:
    print(f"结果是: {result}")
finally:
    print("执行清理工作")

那你就要问了:既然明明知道会可能发生ZeroDivisionError异常,直接设置不能当分母为零不行?首先你的想法很棒!预防性检查比捕获异常更高效,因为异常处理涉及更多的开销。我们可以加一个逻辑先判断分母是否为零,如果为零则打印错误信息。这样可以避免 ZeroDivisionError 异常的发生。但是,如果分母可能在运行时发生变化,或者我们无法控制分母的值,那么使用 try...except 结构来捕获异常会更加安全。即适用场景当输入是动态的或不可控时,或者当程序依赖于外部资源(如文件、网络连接等),而这些资源的状态可能在运行时发生变化。以及在多线程或多进程环境中,资源的状态可能在检查之后发生变化。上面这段话总结一句就是:你无法考虑到所有的情况。

你也可以通过将异常类型放在元组中来捕获多种异常。例如:

try:
    # 可能引发异常的代码
    pass
except (TypeError, ValueError) as e:
    # 处理 TypeError 和 ValueError
    print(f"捕获到异常: {e}") 但是缺点就是不知道到底是哪个异常

自定义异常

尽管 Python 提供了大量的内置异常类型,我们仍然需要创建自己的异常类型来更准确地描述特定的问题。自定义异常通过 继承Python内置异常类 Exception 来实现。例如,ValueErrorTypeError 也都是 Exception 的子类。

1、创建自定义异常

只需要定义一个新的类并让它继承自 Exception 或者其他任何已存在的异常类即可。例如:

class MyCustomError(Exception):
    """这是一个自定义异常的示例"""
    def __init__(self, message="这是一个自定义异常"):
        self.message = message
        super().__init__(self.message)

在这个例子中,MyCustomError 是一个自定义异常类,它有一个可选的消息参数。当这个异常被抛出时,如果提供了消息,那么这个消息就会被用来初始化异常对象。

关于__init__的补充(super涉及到OOP核心思想“继承”)

init 是Python中的构造函数,创建新对象时被自动调用(Javascript中的new 关键字在 JavaScript 中的作用相当于 Python 中的 class 关键字加上 __init__ 方法合而为一)。它接收一个参数 message,默认值是 "这是一个自定义异常"。这意味着如果你不提供任何消息,它会使用这个默认消息。(self 在JavaScript中即this 关键字来引用当前对象。

super() 是一个内置函数,用于调用父类的方法。它返回一个代理对象,代表父类。通过这个代理对象,可以调用父类的方法。 super().__init__(self.message) 的意思是:“调用 Exception 类的 __init__ 方法,并把 self.message 作为参数传递给它。” 这样做的目的是让 Exception 类知道我们传递了一个错误消息。Exception 类的 __init__ 方法会处理这个消息,以便在异常被抛出时能显示它。

  • 第一个 init 是 MyCustomError 类的 init 方法,初始化 MyCustomError 对象的属性。

  • 第二个 init 是通过 super() 调用的 Exception 类的 init 方法,初始化 Exception 对象的属性。

 为什么不能直接在 MyCustomError 的 __init__ 方法中处理消息?
  • 直接在 MyCustomError__init__ 方法中处理消息是可以的,但这样做会失去 Exception 类提供的默认行为。通过调用 Exception 类的 __init__ 方法,我们可以利用 Exception 类已经定义好的逻辑,避免重复代码。具体来说:

    • 利用现有逻辑Exception 类的 __init__ 方法已经定义了如何处理和存储错误消息。如果我们不调用它,就需要自己重新实现这些逻辑,这不仅增加了代码的复杂性,还可能导致错误。
    • 保持一致性:通过调用 Exception 类的 __init__ 方法,我们确保 MyCustomError 异常在行为上与内置的异常一致,这使得代码更加一致和可预测。
    • 扩展性:如果 Exception 类在未来版本的 Python 中进行了改进,我们的 MyCustomError 也能受益于这些改进,
2、抛出异常

使用 raise 关键字可以抛出异常。例如:

def check_value(x):
    if x < 0:
        raise MyCustomError("不能接受负数")
    return x

这里,如果传入的值小于 0,函数 check_value 将会抛出 MyCustomError 异常。

转载自:https://juejin.cn/post/7422575000778489919
评论
请登录