Python异常处理和OOP编程

7 阅读5分钟

异常处理 Try-Except 语法

  • 为什么需要异常处理

    • 避免程序崩溃:处理运行时错误(如文件不存在、网络中断),提升健壮性。
    • 提供友好提示:将错误信息转换为用户易懂的内容。
    • 资源清理:确保文件、网络连接等资源正确释放
  • 基本语法

    try:
        # 可能引发异常的代码
        代码块
    except 异常类型1:
        # 处理异常类型1
        代码块
    except 异常类型2 as e:
        # 处理异常类型2,并获取异常对象e
        代码块
    else:
        # 未发生异常时执行的代码
        代码块
    finally:
        # 无论是否异常,最后都会执行的代码(如资源清理)
        代码块
    
  • 常见异常类型

    异常类型触发场景示例代码
    ZeroDivisionError除以零10 / 0
    FileNotFoundError文件不存在open("missing.txt")
    ValueError类型转换失败int("abc")
    IndexError索引越界lst = [1]; lst[2]
    KeyError字典键不存在d = {"a":1}; d["b"]
    TypeError操作类型不匹配"a" + 1
  • 捕获多个异常

    try:
        with open("test.txt", "r") as f:
            content = f.read()
    except (FileNotFoundError, PermissionError) as e:
        print(e)
    
  • 例:自定义异常类

    class InvalidAgeError(Exception):
        """年龄无效异常"""
        def __init__(self, age):
            self.age = age
            super().__init__(f"年龄{age}无效, 必须大于0! ")
    
    def set_age(age):
        if age <= 0:
            raise InvalidAgeError(age)
        print("年龄设置成功: ", age)
    
    # 测试
    try:
        set_age(-1)
    except InvalidAgeError as e:
        print(e)  # 输出: 年龄-1无效, 必须大于0!
    

Python 面向对象编程 OOP 编程语法

  • 基本结构

    class 类名:
        """类文档字符串"""
        #定义基本属性,类属性 = 初始值 ,所有实例共享,类似java的static静态变量
        name = ""
        #定义私有属性,私有属性在类外部无法直接访问,采用 __ 进行表示,如果方法开头是__ 表示私有方法
        __age = 0
        
        #构造方法
        def __init__(self, 参数1, 参数2):  
            self.实例属性1 = 参数1
            self.实例属性2 = 参数2
    
        #实例方法
        def 实例方法(self):
            """方法文档字符串"""
            return self.实例属性1
            
        #类方法,由哪一个类调用的方法,方法内的cls就是哪一个类的引用
        @classmethod
        def 类方法(cls):
            return cls.类属性
            
        #静态方法,参数随意,没有"self"和"cls"参数,但是方法体中不能使用实例的任何属性和方法
        @staticmethod
        def 静态方法():
            return "与类和实例无关"
    
  • 特殊方法__init__

    • 类有一个名为__init__(self) 的特殊方法(和 Java 的构造函数类似)。该方法在类实例化时会自动调用,默认是无参构造函数。可以有参数,参数通过__init__(self,param1,param2) 传递到类的实例化。
  • self

    • self代表类的实例,而非类,和 Java 中的this类似。当定义一个类,并在类中定义方法时,第一个参数通常被命名为self,尽管可以使用其他名称。方法中需要传递self才可以使用成员变量,它是一个指向实例的引用,使得类的方法能够访问和操作实例的属性。
  • 属性区别(类属性、实例属性)

    • 类属性(所有实例共享)
    • 实例属性(每个对象独立)
  • 核心对比

    特征类属性实例属性
    存储位置类内部定义,类自身维护__init__中定义,实例独立存储
    共享性所有实例共享同一份值每个实例拥有独立副本
    修改影响修改后,所有实例访问到新值修改仅影响当前实例
    内存占用全类共用 1 份内存每个实例单独占用内存
    典型用途常量、计数器、全局配置对象个性化数据

OOP 编程进阶

  • 多个方法对比

    方法类型装饰器第一个参数访问权限典型应用场景
    实例方法无self实例属性和类属性对象的具体行为实现
    类方法@classmethodcls只能访问类属性工厂方法、操作类属性
    静态方法@staticmethod无不能访问实例和类属性工具函数、与类相关的计算
  • cls 方法拓展

  • 在 Python 中cls代表的是类的本身,相对应的self则是类的一个实例对象。
  • cls等同于类本身,类方法中可以通过使用cls来实例化一个对象。

OOP 编程的继承和重写

  • Python 面向对象编程里面的继承

    • 代码复用:子类自动获得父类非私有属性和方法。

    • 扩展性:子类可以添加新属性和方法。

    • 多态基础:不同子类对同一方法的不同实现。

    • 语法特点

      class ParentClass:
          # 父类定义
          pass
          
      class ChildClass(ParentClass):  # 继承语法
          # 子类定义
          pass
      
  • 方法重写

    • 完全重写

      class Vehicle:
          def run(self):
              print("车辆起步")
      
      class Car(Vehicle):
          def run(self):
              print("汽车起步")
      
    • 扩展式重写(使用 super ())

      class Phone:
          def __init__(self, brand):
              self.brand = brand
              
      class SmartPhone(Phone):
          def __init__(self, brand, os):
              super().__init__(brand)  # 调用父类构造
              self.os = os
      

OOP 编程的抽象类和抽象方法

  • 抽象基类

    • Abstract Base Class,简称 ABC,抽象基类是一种不能被实例化的类,主要作用是为其他子类定义一个公共的接口。
  • 抽象方法

    • 抽象方法是定义在抽象基类中的方法,它只有方法签名,没有具体的实现。
    • 子类必须重写抽象方法并提供具体的实现。
  • 代码示例

    from abc import ABC, abstractmethod
    # Shape是一个抽象基类,area是一个抽象方法
    # 因为Shape继承了ABC,且area方法使用了@abstractmethod装饰器,所以Shape不能被实例化,子类必须实现area方法
    class Shape(ABC):
        @abstractmethod
        def area(self):
            pass
            
    class Circle(Shape):
        def __init__(self, radius):
            self.radius = radius
            
        def area(self):
            return 3.14 * self.radius ** 2
    

    在上述代码中:

    • 从abc模块导入ABC类和abstractmethod装饰器 。Shape类继承自ABC,成为抽象基类,其中area方法被@abstractmethod装饰,是抽象方法。
    • Circle类继承自Shape,必须重写area抽象方法,否则会报错。