🧙♂️ 高级魔法师修炼:面向对象编程高级特性
👋 欢迎回到面向对象编程的世界!在入门阶段,我们已经学习了类与对象的基本概念。今天,我们将一起探索Python面向对象编程的高级特性,让你的代码更加优雅、灵活和强大!
🚀 类属性与实例属性的深入理解
在Python中,属性可以分为类属性和实例属性两种类型。我们来系统地学习它们的区别和使用场景。
类属性(Class Attributes)
类属性是定义在类级别上的属性,所有实例共享这一个属性值。
class Car:
# 类属性
total_cars = 0 # 统计创建的汽车总数
manufacturer = "Global Motors"
def __init__(self, brand, model):
self.brand = brand
self.model = model
# 在构造函数中修改类属性
Car.total_cars += 1类属性的特点:
- 定义在类内部,但在所有方法之外
- 所有实例共享同一个类属性值
- 可以通过
ClassName.attribute_name或instance_name.attribute_name访问 - 但只有通过
ClassName.attribute_name修改才能真正改变类属性值
实例属性(Instance Attributes)
实例属性是绑定到特定实例的属性,每个实例都有自己独立的实例属性。
class Car:
def __init__(self, brand, model):
# 实例属性
self.brand = brand # 每个汽车实例都有自己的品牌
self.model = model # 每个汽车实例都有自己的型号
self.mileage = 0 # 每个汽车实例都有自己的里程数实例属性的特点:
- 通常在
__init__方法中定义 - 每个实例有自己独立的属性值
- 只能通过实例访问(
instance_name.attribute_name)
类属性与实例属性的交互
当类属性和实例属性同名时,实例属性会覆盖类属性。
class Car:
color = "白色" # 类属性
def __init__(self, color=None):
if color:
self.color = color # 实例属性,覆盖类属性
# 创建实例
car1 = Car()
print(car1.color) # 输出: 白色(使用类属性)
car2 = Car("红色")
print(car2.color) # 输出: 红色(使用实例属性)
print(Car.color) # 输出: 白色(类属性未被修改)🔧 类方法、静态方法与实例方法
Python中,类可以定义三种类型的方法:实例方法、类方法和静态方法。
实例方法(Instance Methods)
实例方法是我们最常用的方法类型,它自动接收调用它的实例作为第一个参数(通常命名为self)。
class Car:
def __init__(self, brand):
self.brand = brand
# 实例方法
def honk(self):
return f"{self.brand}汽车鸣笛: 滴滴!"类方法(Class Methods)
类方法接收类本身作为第一个参数(通常命名为cls),可以通过@classmethod装饰器定义。
class Car:
total_cars = 0
def __init__(self, brand):
self.brand = brand
Car.total_cars += 1
# 类方法
@classmethod
def get_total_cars(cls):
return f"总共创建了{cls.total_cars}辆汽车"
# 类方法作为替代构造函数
@classmethod
def from_configuration(cls, config_dict):
return cls(config_dict['brand'])类方法的使用场景:
- 访问和修改类属性
- 创建替代构造函数(工厂方法)
- 需要在方法中引用类本身
静态方法(Static Methods)
静态方法不自动接收任何特殊参数,可以通过@staticmethod装饰器定义。
class Car:
# 静态方法
@staticmethod
def is_valid_brand(brand):
valid_brands = ["Toyota", "Honda", "BMW", "Audi"]
return brand in valid_brands静态方法的使用场景:
- 方法逻辑与类或实例的状态无关
- 提供工具函数,与类相关但不需要访问类或实例数据
- 提高代码的组织性(将相关函数放在类内部)
三种方法的对比
| 方法类型 | 第一个参数 | 定义方式 | 访问权限 | 典型用途 |
|---|---|---|---|---|
| 实例方法 | self (实例) | 直接定义 | 类属性、实例属性 | 操作实例状态 |
| 类方法 | cls (类) | @classmethod | 类属性 | 访问/修改类状态、替代构造函数 |
| 静态方法 | 无特殊参数 | @staticmethod | 无特殊访问权 | 提供工具函数 |
🔒 私有属性与私有方法
在Python中,我们可以使用下划线前缀来表示私有属性和方法,这是一种约定而非强制限制。
单下划线前缀(_attribute)
表示"内部使用"的属性或方法,不应该被外部直接访问,但Python不会强制执行。
class Car:
def __init__(self, brand):
self._engine_status = "off" # 内部属性,不建议外部直接访问
def _check_engine(self):
# 内部方法,不建议外部直接调用
return self._engine_status == "on"双下划线前缀(__attribute)
会触发名称修饰(name mangling),Python会将其重命名为_ClassName__attribute,提供更强的"私有"保护。
class Car:
def __init__(self):
self.__max_speed = 200 # 私有属性
def __calculate_fuel_efficiency(self):
# 私有方法
return "高效省油"
# 测试
car = Car()
# 直接访问会报错
# print(car.__max_speed) # AttributeError
# 但仍然可以通过修饰后的名称访问
print(car._Car__max_speed) # 输出: 200属性访问控制
为了更好地控制属性访问,Python提供了属性装饰器(property decorator)。
class Car:
def __init__(self, brand):
self._brand = brand
self._speed = 0
# 属性装饰器,将方法转换为只读属性
@property
def speed(self):
return f"当前速度: {self._speed} km/h"
# setter装饰器,允许修改属性
@speed.setter
def speed(self, value):
if value < 0:
raise ValueError("速度不能为负值")
if value > 200:
raise ValueError("速度不能超过200 km/h")
self._speed = value
# deleter装饰器,允许删除属性
@speed.deleter
def speed(self):
self._speed = 0
print("速度已重置为0")🧬 继承与多态
继承是面向对象编程的核心特性之一,它允许我们创建一个新类,继承现有类的属性和方法。
基本继承
# 父类(基类)
class Vehicle:
def __init__(self, brand):
self.brand = brand
self.speed = 0
def accelerate(self, increment):
self.speed += increment
return f"加速到{self.speed} km/h"
def brake(self, decrement):
self.speed = max(0, self.speed - decrement)
return f"减速到{self.speed} km/h"
# 子类(派生类)
class Car(Vehicle):
def __init__(self, brand, model):
# 调用父类的初始化方法
super().__init__(brand)
self.model = model
self.number_of_doors = 4
def honk(self):
return f"{self.brand} {self.model}鸣笛: 滴滴!"方法重写(Method Overriding)
子类可以重写父类的方法,以提供特定于子类的实现。
class Vehicle:
def start_engine(self):
return "引擎启动"
class ElectricCar(Vehicle):
def start_engine(self):
# 重写父类方法
return "电动汽车安静启动"
class SportsCar(Vehicle):
def start_engine(self):
# 重写父类方法
return "跑车引擎轰鸣启动!"多态(Polymorphism)
多态允许我们使用统一的接口处理不同类型的对象,而不必关心对象的具体类型。
def start_vehicle(vehicle):
# 不关心vehicle是哪个具体子类,只需要它有start_engine方法
print(vehicle.start_engine())
# 创建不同类型的车辆
regular_car = Vehicle()
electric_car = ElectricCar()
sports_car = SportsCar()
# 调用相同的函数处理不同类型的对象
start_vehicle(regular_car) # 输出: 引擎启动
start_vehicle(electric_car) # 输出: 电动汽车安静启动
start_vehicle(sports_car) # 输出: 跑车引擎轰鸣启动!多重继承
Python支持多重继承,一个类可以从多个父类继承属性和方法。
class A:
def method_a(self):
return "Method from A"
class B:
def method_b(self):
return "Method from B"
# 继承自A和B
class C(A, B):
def method_c(self):
# 可以调用A和B的方法
result_a = self.method_a()
result_b = self.method_b()
return f"{result_a} and {result_b}"注意: 多重继承可能导致钻石继承问题(菱形继承),Python使用C3线性化算法来解决这个问题,决定方法解析顺序(MRO)。
✨ 魔术方法(特殊方法)
Python中有许多以双下划线开头和结尾的特殊方法,通常称为魔术方法(Magic Methods)或双下方法(Dunder Methods)。这些方法允许我们自定义类的行为。
常用魔术方法
初始化和销毁
__init__(self, ...): 初始化对象,当创建新实例时调用__del__(self): 当对象被垃圾回收时调用
字符串表示
__str__(self): 返回对象的字符串表示,用于str()和print()__repr__(self): 返回对象的"官方"字符串表示,用于repr()
class Car:
def __init__(self, brand, model):
self.brand = brand
self.model = model
def __str__(self):
return f"{self.brand} {self.model}"
def __repr__(self):
return f"Car(brand='{self.brand}', model='{self.model}')"运算符重载
__add__(self, other): 实现加法运算__sub__(self, other): 实现减法运算__mul__(self, other): 实现乘法运算__truediv__(self, other): 实现除法运算__eq__(self, other): 实现相等性比较==__lt__(self, other): 实现小于比较<__gt__(self, other): 实现大于比较>
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
def __str__(self):
return f"Vector({self.x}, {self.y})"容器行为
__len__(self): 返回对象长度,用于len()__getitem__(self, key): 获取索引或键对应的值,用于[]操作__setitem__(self, key, value): 设置索引或键对应的值__contains__(self, item): 判断元素是否在容器中,用于in操作符
class ShoppingCart:
def __init__(self):
self.items = []
def add_item(self, item):
self.items.append(item)
def __len__(self):
return len(self.items)
def __getitem__(self, index):
return self.items[index]
def __contains__(self, item):
return item in self.items🎯 抽象基类
抽象基类(Abstract Base Classes,ABCs)定义了接口规范,确保子类实现特定的方法。
from abc import ABC, abstractmethod
# 定义抽象基类
class Shape(ABC):
@abstractmethod
def area(self):
# 抽象方法,子类必须实现
pass
@abstractmethod
def perimeter(self):
# 抽象方法,子类必须实现
pass
# 具体子类
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
# 具体子类
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
import math
return math.pi * self.radius ** 2
def perimeter(self):
import math
return 2 * math.pi * self.radius注意: 不能直接实例化抽象基类,必须通过实现了所有抽象方法的具体子类来创建实例。
🔍 元编程初步
元编程是指编写能够操作代码的代码。在Python中,我们可以通过反射、装饰器、元类等方式实现元编程。
反射(Reflection)
反射是指程序能够访问、检测和修改其自身状态或行为的能力。
class Car:
def __init__(self, brand, model):
self.brand = brand
self.model = model
def honk(self):
return "鸣笛: 滴滴!"
# 创建实例
car = Car("Toyota", "Corolla")
# 检查对象的属性和方法
print(dir(car)) # 列出对象的所有属性和方法
print(hasattr(car, "brand")) # 检查对象是否有brand属性
print(getattr(car, "brand")) # 获取对象的brand属性值
setattr(car, "year", 2023) # 设置对象的year属性
print(car.year) # 输出: 2023🛠️ 实际应用示例
让我们通过一个综合示例来巩固所学的面向对象编程高级特性。
from abc import ABC, abstractmethod
# 抽象基类
class PaymentMethod(ABC):
@abstractmethod
def pay(self, amount):
pass
# 具体支付方式
class CreditCardPayment(PaymentMethod):
def __init__(self, card_number, holder_name):
self._card_number = card_number # 内部属性
self.holder_name = holder_name
def pay(self, amount):
# 实际应用中会有更复杂的支付逻辑
return f"使用信用卡 {self._mask_card_number()} 支付 ¥{amount}"
def _mask_card_number(self):
# 私有方法,隐藏卡号的中间部分
return f"****-****-****-{self._card_number[-4:]}"
class AlipayPayment(PaymentMethod):
def __init__(self, account_id):
self.account_id = account_id
def pay(self, amount):
return f"使用支付宝 {self.account_id} 支付 ¥{amount}"
# 订单类
class Order:
# 类属性
order_count = 0
def __init__(self, items):
# 自增订单计数
Order.order_count += 1
self.order_id = Order.order_count
self.items = items
self.status = "待支付"
self.payment_method = None
# 计算订单总金额
def calculate_total(self):
return sum(item['price'] * item['quantity'] for item in self.items)
# 设置支付方式
def set_payment_method(self, payment_method):
self.payment_method = payment_method
# 处理支付
def process_payment(self):
if not self.payment_method:
raise ValueError("请先设置支付方式")
total = self.calculate_total()
result = self.payment_method.pay(total)
self.status = "已支付"
return result
# 字符串表示
def __str__(self):
return f"订单 #{self.order_id}: {self.status}"
# 使用示例
if __name__ == "__main__":
# 创建订单
order_items = [
{"name": "Python编程书籍", "price": 99, "quantity": 1},
{"name": "编程鼠标垫", "price": 29, "quantity": 2}
]
order = Order(order_items)
# 设置支付方式
credit_card = CreditCardPayment("1234567890123456", "张三")
order.set_payment_method(credit_card)
# 处理支付
payment_result = order.process_payment()
print(order)
print(payment_result)
print(f"订单总计: ¥{order.calculate_total()}")💡 最佳实践
- 封装:使用私有属性和方法保护内部实现细节
- 继承:遵循"里氏替换原则",确保子类可以替换父类使用
- 组合优先于继承:当不需要继承的全部功能时,考虑使用组合
- 合理使用特殊方法:但不要滥用,保持代码可读性
- 使用抽象基类:定义清晰的接口规范
- 属性访问控制:使用
@property装饰器管理属性访问 - 类方法与静态方法:根据实际需求选择合适的方法类型
🚩 互动小练习
扩展订单系统:为订单系统添加更多功能,如订单取消、订单状态跟踪等。
创建图形类层次结构:
- 创建一个抽象基类
Shape,定义area()和perimeter()抽象方法 - 实现具体的图形类:
Triangle(三角形)、Square(正方形)、Polygon(多边形)等 - 确保每个类都正确实现了抽象方法
- 创建一个抽象基类
实现自定义容器类:
- 创建一个自定义的列表类
SortedList,始终保持元素有序 - 实现
__getitem__、__setitem__、__len__、__contains__等魔术方法 - 添加
add、remove等常用操作方法
- 创建一个自定义的列表类
模拟银行账户系统:
- 创建
Account基类,实现存款、取款等基本功能 - 创建
SavingsAccount(储蓄账户)和CheckingAccount(支票账户)子类 - 为不同账户类型实现不同的利息计算方式和费用规则
- 创建
通过本节课的学习,你已经掌握了Python面向对象编程的高级特性。这些技能将帮助你编写更加模块化、可扩展和可维护的代码。记得在实际项目中多加练习,将这些概念应用到实际场景中! 通过本节课的学习,你已经掌握了Python面向对象编程的高级特性。这些技能将帮助你编写更加模块化、可扩展和可维护的代码。记得在实际项目中多加练习,将这些概念应用到实际场景中!
下节课,我们将深入学习异常处理的进阶知识,让你的程序更加健壮!🚀




