【Python基础 | 第5章】面向对象与异常处理:一文搞懂类、对象、封装、继承、多态

目录名称

    • 前言
    • [1. 面向对象](#1. 面向对象)
      • [1.1 面向对象基础](#1.1 面向对象基础)
      • [1.2 封装](#1.2 封装)
      • [1.3 继承](#1.3 继承)
      • [1.4 多态](#1.4 多态)
      • [1.5 魔法方法](#1.5 魔法方法)
      • [1.6 实例属性与类属性](#1.6 实例属性与类属性)
    • [2. 异常](#2. 异常)
      • [2.1 定义](#2.1 定义)
      • [2.2 异常处理](#2.2 异常处理)
      • [2.3 异常的传递](#2.3 异常的传递)
    • 结语

🎬 博主名称: 超级苦力怕

🔥 个人专栏: 《Python 基础》

🚀 每一次思考都是突破的前奏,每一次复盘都是精进的开始!


前言

本文是 Python 基础系列的核心篇章,系统讲解面向对象编程 (类、对象、封装、继承、多态、魔法方法、类属性与实例属性)以及异常处理机制

1. 面向对象

1.1 面向对象基础

面向过程 :把一个需求分解成一系列要执行的步骤,然后依次执行(关注流程、步骤),适合简单、线性的任务。

:一组具有相同属性(特征)和方法(功能/行为)的模板。
对象:面向对象编程的基本单元,是类的实例,将数据和操作打包在一起。

提示:对象是由类创建出来的,一个类可以创建无数个对象,创建对象的过程也叫对象的实例化。

python 复制代码
# 定义类
class 类名:
    def __init__(self, 参数列表):			# 函数定义在类里,叫方法
        self.属性名 = 参数值					# 变量定义在类里,叫属性
        self.属性名 = 参数值

    def 方法名(self, 形参列表):
        # 方法体
        pass

# 创建对象
对象名 = 类名(参数值1, 参数值2)

示例

python 复制代码
class Car:
    def __init__(self, brand, name, price):
        self.brand = brand
        self.name = name
        self.price = price

    def running(self):
        print(f"{self.brand} {self.name} 正在行驶...")

# 创建对象
c1 = Car("BMW", "X5", 500000)
c1.running()

说明

  • 类名采用大驼峰命名法,每个单词首字母都是大写,单位之间没有分隔符(如 UserAccount)。
  • __init__ 是初始化方法,在对象创建时自动调用,用于初始化属性;self 代表当前实例,调用时无需传递。
  • 通过 对象.属性对象.方法() 访问成员。

1.2 封装

封装:将数据(属性)和操作数据的方法(行为)包装在类内部,对外隐藏实现细节,只暴露必要的接口。通过控制属性的访问权限,保证数据安全。

Python 中没有严格的访问控制,通常使用单下划线 _ 或双下划线 __ 表示"受保护的"或"私有的"属性,并提供 getter/setter 方法

python 复制代码
class BankAccount:
    def __init__(self, owner, balance):
        self.owner = owner
        self.__balance = balance          # 私有属性

    # getter 方法:获取余额
    def get_balance(self):
        return self.__balance

    # setter 方法:修改余额(带校验)
    def set_balance(self, amount):
        if amount < 0:
            print("余额不能为负数")
            return
        self.__balance = amount

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            print(amount)          # 仅打印存入金额
        else:
            print("存款金额必须为正数")

    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            print(amount)          # 仅打印取出金额
        else:
            print("余额不足或金额无效")

# 存钱
acc = BankAccount("张三", 1000)
acc.deposit(500)          # 输出: 500
acc.withdraw(200)         # 输出: 200
print(acc.get_balance())  # 输出: 1300

# 通过 setter 修改余额
acc.set_balance(2000)
print(acc.get_balance())  # 输出: 2000

# 尝试直接访问私有属性会报错(但可通过特殊方式访问,不推荐)
# print(acc.__balance)    # AttributeError

拓展: 也可以使用@property 装饰器来实现封装

@property:定义 getter 方法,当我们获取 balance 的时候,会自动执行这个方法,返回 self.__balance
@balance.setter:定义 setter 方法,当执行 acc.balance = 2000 时,会自动调用该方法,将等号右边的值传入。

python 复制代码
class BankAccount:
    def __init__(self, owner, balance):
        self.owner = owner
        self.__balance = balance

    @property
    def balance(self):
        return self.__balance

    @balance.setter
    def balance(self, amount):
        if amount < 0:
            print("余额不能为负数")
            return
        self.__balance = amount

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            print(amount)
        else:
            print("存款金额必须为正数")

    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            print(amount)
        else:
            print("余额不足或金额无效")

# ---------- 使用示例(补充) ----------
acc2 = BankAccount("李四", 2000)
print(acc2.balance)      # 通过属性直接获取余额,输出 2000
acc2.balance = 3000      # 通过属性直接设置余额(调用 setter)
print(acc2.balance)      # 输出 3000
acc2.deposit(500)        # 输出 500
print(acc2.balance)      # 输出 3500

注意

  • 封装是一种约定和防意外的机制,并非严格的安全保障
  • 封装的好处:通过 getter/setter 控制数据读写逻辑,避免外部直接赋值无效值,同时可以在内部进行数据校验类型转换 、以及触发其他操作,提高代码可维护性。

1.3 继承

继承:子类可以继承父类的属性和方法,实现代码复用,并可以在子类中扩展或重写父类的功能。

python 复制代码
# 父类
class Vehicle:
    def __init__(self, brand, model):
        self.brand = brand
        self.model = model

    def start(self):
        print(self.brand, self.model, "启动...")

# 子类
class Car(Vehicle):
    def __init__(self, brand, model, doors):
        super().__init__(brand, model)   # 调用父类构造方法
        self.doors = doors

    def honk(self):
        print(self.brand, self.model, "鸣笛:滴滴~")

# 使用
car = Car("BMW", "X5", 4)
car.start()    # 输出:BMW X5 启动...
car.honk()     # 输出:BMW X5 鸣笛:滴滴~

方法重写:子类可以重新定义父类中的方法,提供自己的实现。

python 复制代码
class ElectricCar(Car):
    def __init__(self, brand, model, doors, battery):
        super().__init__(brand, model, doors)
        self.battery = battery

    # 重写 start 方法
    def start(self):
        print(self.brand, self.model, "无声启动,电量", self.battery, "kWh")

e_car = ElectricCar("Tesla", "Model 3", 4, 75)
e_car.start()   # 输出:Tesla Model 3 无声启动,电量 75 kWh

注意

  • super() 用于调用父类的方法,确保父类的初始化逻辑被执行。
  • Python 支持多重继承(一个子类可继承多个父类),但复杂场景下容易引发问题,建议谨慎使用。

1.4 多态

多态:同一操作作用于不同对象时,可以产生不同的执行结果。它允许使用统一的方式处理不同类型的对象,提高代码的灵活性和可扩展性。

python 复制代码
def vehicle_test(vehicle):
    """统一接口,不同对象表现出不同行为"""
    vehicle.start()

# 创建不同类型的对象
vehicles = [
    Car("Audi", "A6", 4),
    ElectricCar("Tesla", "Model 3", 4, 75)
]

for v in vehicles:
    vehicle_test(v)   # 自动调用各自类中的 start 方法

多态的实现不依赖特殊的语法,只需保证不同类中有相同名称的方法即可。Python 进一步强化了多态:只要对象有需要的方法,就可以当作所需类型使用。

python 复制代码
class Bicycle:
    def start(self):
        print("自行车开始骑行")

vehicles.append(Bicycle())
vehicle_test(vehicles[-1])   # 输出:自行车开始骑行

1.5 魔法方法

魔法方法(特殊方法)是以双下划线开头和结尾的方法,Python 会在特定场景下自动调用,用于定义类的特殊行为。

魔法方法 描述
__init__(self, ...) 构造方法,创建对象时自动调用
__str__(self) 定义 print(对象)str(对象) 的输出内容
__repr__(self) 定义对象的官方字符串表示,常用于调试
__eq__(self, other) 定义 == 操作符的行为
__lt__(self, other) 定义 < 操作符的行为,其他比较操作符类似
__len__(self) 定义 len(对象) 的行为
__getitem__(self, key) 定义通过索引或键访问元素的行为

示例

python 复制代码
class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score

    def __str__(self):
        return f"学生:{self.name},成绩:{self.score}"

    def __eq__(self, other):
        return self.score == other.score

    def __lt__(self, other):
        return self.score < other.score

s1 = Student("张三", 85)
s2 = Student("李四", 92)
print(s1)               # 输出:学生:张三,成绩:85
print(s1 == s2)         # False
print(s1 < s2)          # True

注意:魔法方法不需要手动调用,Python 在相应操作发生时自动调用它们。


1.6 实例属性与类属性

  • 实例属性 :属于每个具体对象,通过 self 定义,每个对象独立拥有。
  • 类属性 :属于类本身,所有实例共享,通过类名或 self.__class__ 访问,常用于配置或共享数据。
python 复制代码
class Car:
    # 类属性(所有实例共享)
    wheels = 4
    tax_rate = 0.1

    def __init__(self, brand, name, price):
        # 实例属性(每个对象独立)
        self.brand = brand
        self.name = name
        self.price = price

    def total_cost(self):
        # 访问实例属性 price 和类属性 tax_rate
        return self.price * (1 + Car.tax_rate)

# 访问类属性
print(Car.wheels)        # 4
c1 = Car("BMW", "X5", 500000)
c2 = Car("Audi", "A6", 450000)

print(c1.wheels)         # 4(通过实例也能访问类属性)
print(c2.total_cost())   # 495000.0

# 修改类属性会影响所有实例
Car.tax_rate = 0.12
print(c1.total_cost())   # 560000.0

查找顺序:当通过实例访问属性时,Python 会先查找实例属性,如果不存在则查找类属性。实例属性会"遮盖"同名的类属性,但类属性本身不会被修改。

python 复制代码
c1.wheels = 3            # 为实例 c1 添加实例属性 wheels,不会影响类属性
print(c1.wheels)         # 3
print(Car.wheels)        # 4
print(c2.wheels)         # 4

2. 异常

2.1 定义

异常:程序运行过程中出现的错误,会中断程序的正常执行流程

作用:

  • 保证数据、逻辑正确性,避免程序执行混乱
  • 在开发阶段,尽量发现更多问题,尽早解决,保障程序正常执行

2.2 异常处理

程序运行过程出现异常,我们可以选择 不做处理捕获异常 ,如果我们捕获并处理异常,程序会继续执行(编写程序做好预案,出现异常按预案处理)。

当程序处于 try 语句内报错,会从上至下匹配,直到匹配成功,进行解决,程序继续运行

python 复制代码
# 定义语法
try:
	可能出现异常的业务代码1
	可能出现异常的业务代码2
	...
except [异常类型 as 变量名]
	出现异常时预案
finally:
	不管是否出现异常都会执行的代码

# 示例
try:
    print("=")
    print(my_name)				# 这里没有定义该变量,会被捕获
    print("=")
except NameError as e:
    print("程序运行报错,错误信息:", e)
finally:
    print("释放资源 ~")

2.3 异常的传递

一场传递就是异常在函数调用中层层上报的过程,直到有人处理它或程序崩溃

python 复制代码
def fun1():
    print("fun1 ... running ...")
    fun2()  # 调用fun2,异常会从这里传递上去

def fun2():
    print("fun2 ... running ...")
    fun3()  # 调用fun3,异常会从这里传递上去

def fun3():
    print("fun3 ... running ...")
    print(my_color)  # NameError: name 'my_color' is not defined,异常在这里发生

if __name__ == '__main__':
    fun1()  # 调用fun1,异常会沿着调用链传递到这里

结语

本文全面讲解了 Python 面向对象编程(类、对象、封装、继承、多态、魔法方法、属性分类)以及异常处理的核心知识。通过这篇文章,能够理解如何设计类、控制访问、复用代码、处理运行时错误。

  • 如果本文对你有帮助:欢迎点赞、收藏,让更多正在学 Python 的同学看到。
  • 遇到问题或有不同理解:可以在评论区留言,一起讨论、互相学习。
  • 想系统看更多内容:可以关注专栏《Python 基础》,一起把基础打牢。
相关推荐
啦啦啦!2 小时前
项目环境的搭建,项目的初步使用和deepseek的初步认识
开发语言·c++·人工智能·算法
YanDDDeat2 小时前
【大模型微调】基于 Llama3-8B 的 LoRA 微调专有领域QA 问答对生成模型
python·语言模型·llama
小李云雾2 小时前
Python Web 路由详解:核心知识点全覆盖
开发语言·前端·python·路由
鲸渔2 小时前
【C++ 变量与常量】变量的定义、初始化、const 与 constexpr
java·开发语言·c++
不会写DN2 小时前
SQL 单表操作全解
java·服务器·开发语言·数据库·sql
翻斗包菜2 小时前
零基础入门 Flask 框架
后端·python·flask
平安的平安2 小时前
Python 实现 AI 图像生成:调用 Stable Diffusion API 完整教程
人工智能·python·stable diffusion
_下雨天.2 小时前
Flask 框架
后端·python·flask
卤炖阑尾炎2 小时前
Flask 框架实战全解:从入门到精通
后端·python·flask