目录名称

🎬 博主名称: 超级苦力怕
🔥 个人专栏: 《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 基础》,一起把基础打牢。
