引言:面向对象编程的核心概念
面向对象编程(Object-Oriented Programming,简称OOP)是现代软件开发中最重要和最流行的编程范式之一。Python作为一门支持多范式的编程语言,对OOP提供了出色的支持。在本篇文章中,我们将深入探讨Python中面向对象编程的各个方面,从基础概念到高级应用,帮助您全面掌握这一强大的编程范式。
面向对象编程的核心思想是将现实世界中的实体抽象为程序中的”对象”。每个对象都包含数据(属性)和操作数据的方法(行为)。这种编程方式更符合人类的自然思维方式,使代码更加模块化、可重用和易于维护。
让我们通过一个简单的例子来理解OOP的基本概念:
# 定义一个简单的类:汽车
class Car:
# 初始化方法(构造函数)
def __init__(self, brand, model, color):
self.brand = brand # 品牌属性
self.model = model # 型号属性
self.color = color # 颜色属性
self.speed = 0 # 速度属性,默认为0
# 方法:加速
def accelerate(self, amount):
self.speed += amount
print(f"{self.brand} {self.model} 加速到 {self.speed} km/h")
# 方法:刹车
def brake(self, amount):
if self.speed >= amount:
self.speed -= amount
print(f"{self.brand} {self.model} 减速到 {self.speed} km/h")
else:
self.speed = 0
print(f"{self.brand} {self.model} 已完全停止")
# 方法:显示车辆信息
def display_info(self):
return f"车辆信息: {self.color} {self.brand} {self.model}, 当前速度: {self.speed} km/h"
# 创建汽车对象
my_car = Car("Toyota", "Camry", "黑色")
print(my_car.display_info())
my_car.accelerate(60)
my_car.brake(20)
print(my_car.display_info())
这个例子展示了OOP的几个关键元素:
- 类(Class):Car是定义汽车的蓝图
- 属性(Attributes):brand, model, color, speed存储对象的状态
- 方法(Methods):accelerate, brake, display_info定义对象的行为
- 对象(Object):my_car是Car类的具体实例
类与对象:Python OOP的基础
类的定义与实例化
在Python中,类使用class关键字定义。类名通常采用驼峰命名法(CamelCase),而方法和属性使用蛇形命名法(snake_case)。
class Dog:
# 类属性(所有实例共享)
species = "Canis familiaris"
# 实例初始化方法
def __init__(self, name, age, breed):
# 实例属性(每个实例独立)
self.name = name
self.age = age
self.breed = breed
# 实例方法
def bark(self):
return f"{self.name} 正在汪汪叫!"
def human_age(self):
return f"{self.name} 的人类年龄是 {self.age * 7} 岁"
# 创建Dog类的实例
dog1 = Dog("Buddy", 3, "Golden Retriever")
dog2 = Dog("Max", 5, "German Shepherd")
# 访问属性和方法
print(dog1.name) # 输出: Buddy
print(dog2.bark()) # 输出: Max 正在汪汪叫!
print(Dog.species) # 输出: Canis familiaris
print(dog1.human_age()) # 输出: Buddy 的人类年龄是 21 岁
self参数详解
在Python类的方法中,第一个参数通常是self,它代表类的当前实例。通过self,我们可以访问实例的属性和方法。虽然在调用方法时不需要显式传递self(Python会自动处理),但在方法定义中必须包含它。
class Rectangle:
def __init__(self, width, height):
# 这里的self代表新创建的实例
self.width = width
self.height = height
def area(self):
# 通过self访问实例属性
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
def is_square(self):
# 在类的方法中调用另一个方法也需要self
return self.width == self.height
# 创建实例
rect = Rectangle(5, 10)
print(f"面积: {rect.area()}") # 输出: 面积: 50
print(f"周长: {rect.perimeter()}") # 输出: 周长: 30
print(f"是正方形吗? {rect.is_square()}") # 输出: 是正方形吗? False
类属性与实例属性
Python中有两种类型的属性:
- 类属性:属于类本身,所有实例共享
- 实例属性:属于特定实例,每个实例独立
class Employee:
# 类属性
company = "TechCorp"
employee_count = 0
def __init__(self, name, position):
# 实例属性
self.name = name
self.position = position
Employee.employee_count += 1 # 每次创建实例时增加计数
@classmethod
def get_employee_count(cls):
return f"公司共有 {cls.employee_count} 名员工"
# 创建员工实例
emp1 = Employee("Alice", "Developer")
emp2 = Employee("Bob", "Designer")
# 访问类属性
print(Employee.company) # 输出: TechCorp
print(Employee.get_employee_count()) # 输出: 公司共有 2 名员工
# 实例也可以访问类属性
print(emp1.company) # 输出: TechCorp
# 修改类属性会影响所有实例
Employee.company = "NewTechCorp"
print(emp2.company) # 输出: NewTechCorp
继承与多态:扩展和重用代码
单继承与方法重写
继承允许一个类(子类)基于另一个类(父类)来创建。子类会继承父类的所有属性和方法,并可以添加新的属性和方法,或重写已有的方法。
# 父类:动物
class Animal:
def __init__(self, name, species):
self.name = name
self.species = species
def speak(self):
return f"{self.name} 发出声音"
def __str__(self):
return f"{self.name} ({self.species})"
# 子类:猫,继承自Animal
class Cat(Animal):
def __init__(self, name, color, lives=9):
# 调用父类的初始化方法
super().__init__(name, "Felis catus")
self.color = color
self.lives = lives
# 重写父类的speak方法
def speak(self):
return f"{self.name} 说: 喵喵喵!"
# 子类特有方法
def lose_life(self):
if self.lives > 0:
self.lives -= 1
return f"{self.name} 失去了一条生命,还剩 {self.lives} 条"
else:
return f"{self.name} 已经没有生命了"
# 创建实例
generic_animal = Animal("某动物", "未知物种")
my_cat = Cat("Whiskers", "橘色", 9)
# 测试继承和方法重写
print(generic_animal.speak()) # 输出: 某动物 发出声音
print(my_cat.speak()) # 输出: Whiskers 说: 喵喵喵!
print(my_cat) # 输出: Whiskers (Felis catus)
print(my_cat.lose_life()) # 输出: Whiskers 失去了一条生命,还剩 8 条
多继承与MRO(方法解析顺序)
Python支持多继承,即一个类可以同时继承多个父类。当多个父类有同名方法时,Python使用C3线性化算法确定方法解析顺序(MRO)。
class Flyer:
def __init__(self, name):
self.name = name
def move(self):
return f"{self.name} 在飞行"
class Swimmer:
def __init__(self, name):
self.name = name
def move(self):
return f"{self.name} 在游泳"
# 多继承:鸭子既会飞又会游
class Duck(Flyer, Swimmer):
def __init__(self, name):
# 注意:这里只调用第一个父类的__init__
Flyer.__init__(self, name)
def move(self):
# 可以选择调用特定父类的方法
return f"{self.name} 说: 我可以同时飞行和游泳!\n" \
f" 飞行: {Flyer.move(self)}\n" \
f" 游泳: {Swimmer.move(self)}"
# 查看MRO
print(Duck.mro())
# 输出: [<class '__main__.Duck'>, <class '__main__.Flyer'>, <class '__main__.Swimmer'>, <class 'object'>]
donald = Duck("Donald")
print(donald.move())
# 输出:
# Donald 说: 我可以同时飞行和游泳!
# 飞行: Donald 在飞行
# 游泳: Donald 在游泳
多态性
多态是指不同类的对象对同一消息做出不同的响应。在Python中,多态通过方法重写实现,不需要显式的接口定义。
class Shape:
def area(self):
pass
def perimeter(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14159 * self.radius ** 2
def perimeter(self):
return 2 * 3.14159 * self.radius
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 Triangle(Shape):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def area(self):
# 使用海伦公式
s = (self.a + self.b + self.c) / 2
return (s * (s - self.a) * (s - self.b) * (s - self.c)) ** 0.5
def perimeter(self):
return self.a + self.b + self.c
# 多态示例:统一处理不同形状
def print_shape_info(shape):
print(f"形状: {shape.__class__.__name__}")
print(f"面积: {shape.area():.2f}")
print(f"周长: {shape.perimeter():.2f}")
print("-" * 30)
# 创建不同形状对象
shapes = [
Circle(5),
Rectangle(4, 6),
Triangle(3, 4, 5)
]
# 统一处理
for shape in shapes:
print_shape_info(shape)
封装与访问控制
公有与私有成员
Python通过命名约定实现访问控制,而不是严格的访问修饰符。单下划线_表示保护成员,双下划线__表示私有成员(名称修饰)。
class BankAccount:
def __init__(self, account_holder, initial_balance=0):
self.account_holder = account_holder # 公有属性
self._balance = initial_balance # 保护属性(约定)
self.__pin = "1234" # 私有属性(名称修饰)
def deposit(self, amount):
if amount > 0:
self._balance += amount
return f"存入 {amount},当前余额: {self._balance}"
else:
return "存款金额必须大于0"
def withdraw(self, amount, pin):
if pin != self.__pin:
return "PIN码错误"
if amount <= 0:
return "取款金额必须大于0"
if amount > self._balance:
return "余额不足"
self._balance -= amount
return f"取出 {amount},当前余额: {self._balance}"
def get_balance(self, pin):
if pin == self.__pin:
return self._balance
return "PIN码错误"
# 使用示例
account = BankAccount("John Doe", 1000)
print(account.account_holder) # 公有属性,可以访问
print(account._balance) # 保护属性,可以访问但不建议
# print(account.__pin) # 会报错:AttributeError
# 通过方法访问私有属性
print(account.get_balance("1234")) # 正确方式
# 尝试直接访问私有属性会失败
try:
print(account.__pin)
except AttributeError as e:
print(f"错误: {e}")
# 实际上可以通过名称修饰访问(但不推荐)
print(f"通过名称修饰访问: {account._BankAccount__pin}")
属性装饰器
Python提供了@property装饰器,可以将方法转换为属性,实现更优雅的封装。
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
"""获取摄氏温度"""
return self._celsius
@celsius.setter
def celsius(self, value):
"""设置摄氏温度"""
if value < -273.15:
raise ValueError("温度不能低于绝对零度")
self._celsius = value
@property
def fahrenheit(self):
"""华氏温度(只读属性)"""
return (self._celsius * 9/5) + 32
@fahrenheit.setter
def fahrenheit(self, value):
"""通过华氏温度设置"""
self.celsius = (value - 32) * 5/9 # 使用celsius的setter
# 使用示例
temp = Temperature(25)
print(f"当前温度: {temp.celsius}°C") # 使用getter
print(f"华氏温度: {temp.fahrenheit}°F") # 使用getter
# 修改温度(使用setter)
temp.celsius = 30
print(f"新温度: {temp.celsius}°C")
# 通过华氏温度设置
temp.fahrenheit = 68
print(f"通过68°F设置后: {temp.celsius}°C")
# 尝试设置无效温度
try:
temp.celsius = -300
except ValueError as e:
print(f"错误: {e}")
特殊方法(魔术方法)
Python类可以定义特殊方法(以双下划线开头和结尾),这些方法允许类与Python内置函数和操作符交互。
常用特殊方法示例
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
# __str__:定义str()和print()的行为
def __str__(self):
return f"Vector({self.x}, {self.y})"
# __repr__:定义repr()和交互式环境中的显示
def __repr__(self):
return f"Vector({self.x}, {self.y})"
# __add__:定义+运算符
def __add__(self, other):
if isinstance(other, Vector):
return Vector(self.x + other.x, self.y + other.y)
return NotImplemented
# __sub__:定义-运算符
def __sub__(self, other):
if isinstance(other, Vector):
return Vector(self.x - other.x, self.y - other.y)
return NotImplemented
# __mul__:定义*运算符(标量乘法)
def __mul__(self, scalar):
if isinstance(scalar, (int, float)):
return Vector(self.x * scalar, self.y * scalar)
return NotImplemented
# __rmul__:定义右乘(当乘法顺序反过来时)
def __rmul__(self, scalar):
return self.__mul__(scalar)
# __eq__:定义==运算符
def __eq__(self, other):
if isinstance(other, Vector):
return self.x == other.x and self.y == other.y
return False
# __len__:定义len()函数
def __len__(self):
return int((self.x ** 2 + self.y ** 2) ** 0.5)
# __getitem__:定义索引访问
def __getitem__(self, index):
if index == 0:
return self.x
elif index == 1:
return self.y
raise IndexError("Vector index out of range")
# __setitem__:定义索引赋值
def __setitem__(self, index, value):
if index == 0:
self.x = value
elif index == 1:
self.y = value
else:
raise IndexError("Vector index out of range")
# 使用示例
v1 = Vector(2, 3)
v2 = Vector(1, 4)
print(v1) # __str__: Vector(2, 3)
print(v1 + v2) # __add__: Vector(3, 7)
print(v1 * 3) # __mul__: Vector(6, 9)
print(2 * v1) # __rmul__: Vector(4, 6)
print(v1 == Vector(2, 3)) # __eq__: True
print(len(v1)) # __len__: 3 (sqrt(2^2+3^2))
print(v1[0], v1[1]) # __getitem__: 2 3
v1[0] = 5 # __setitem__
print(v1) # Vector(5, 3)
类方法与静态方法
类方法(@classmethod)
类方法的第一个参数是类本身(通常命名为cls),可以访问和修改类状态,但不能访问实例状态。
class Pizza:
def __init__(self, ingredients, size):
self.ingredients = ingredients
self.size = size
def __repr__(self):
return f"Pizza({self.ingredients}, {self.size})"
@classmethod
def margherita(cls, size):
"""工厂方法:制作玛格丽特披萨"""
return cls(["mozzarella", "tomato"], size)
@classmethod
def pepperoni(cls, size):
"""工厂方法:制作辣香肠披萨"""
return cls(["mozzarella", "tomato", "pepperoni"], size)
@classmethod
def get_pizza_info(cls):
"""获取披萨类的信息"""
return f"我们提供 {cls.__name__},有多种口味可选"
# 使用工厂方法创建披萨
p1 = Pizza.margherita("large")
p2 = Pizza.pepperoni("medium")
print(p1) # Pizza(['mozzarella', 'tomato'], large)
print(p2) # Pizza(['mozzarella', 'tomato', 'pepperoni'], medium)
print(Pizza.get_pizza_info()) # 我们提供 Pizza,有多种口味可选
静态方法(@staticmethod)
静态方法既不访问类状态也不访问实例状态,它们只是位于类命名空间中的普通函数。
class MathUtils:
@staticmethod
def add(a, b):
"""静态方法:两数相加"""
return a + b
@staticmethod
def multiply(a, b):
"""静态方法:两数相乘"""
return a * b
@staticmethod
def is_prime(n):
"""静态方法:判断是否为质数"""
if n <= 1:
return False
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
return False
return True
# 使用静态方法(无需创建实例)
print(MathUtils.add(5, 3)) # 8
print(MathUtils.multiply(4, 7)) # 28
print(MathUtils.is_prime(17)) # True
print(MathUtils.is_prime(15)) # False
# 也可以通过实例调用
math_utils = MathUtils()
print(math_utils.add(10, 20)) # 30
抽象基类与接口
Python的abc模块提供了定义抽象基类(Abstract Base Class)的工具,用于强制子类实现特定方法。
from abc import ABC, abstractmethod
class PaymentProcessor(ABC):
"""支付处理器的抽象基类"""
@abstractmethod
def process_payment(self, amount):
"""处理支付,子类必须实现"""
pass
@abstractmethod
def refund(self, transaction_id):
"""退款,子类必须实现"""
pass
def validate_amount(self, amount):
"""非抽象方法,子类可以直接使用"""
if amount <= 0:
raise ValueError("金额必须大于0")
return True
class CreditCardProcessor(PaymentProcessor):
def __init__(self, merchant_id):
self.merchant_id = merchant_id
def process_payment(self, amount):
self.validate_amount(amount)
# 模拟信用卡处理逻辑
transaction_id = f"CC-{self.merchant_id}-{int(amount)}"
print(f"信用卡支付处理成功: 金额={amount}, 交易ID={transaction_id}")
return transaction_id
def refund(self, transaction_id):
print(f"信用卡退款处理: 交易ID={transaction_id}")
return f"REFUND-{transaction_id}"
class PayPalProcessor(PaymentProcessor):
def __init__(self, email):
self.email = email
def process_payment(self, amount):
self.validate_amount(amount)
# 模拟PayPal处理逻辑
transaction_id = f"PP-{self.email.split('@')[0]}-{int(amount)}"
print(f"PayPal支付处理成功: 金额={amount}, 交易ID={transaction_id}")
return transaction_id
def refund(self, transaction_id):
print(f"PayPal退款处理: 交易ID={transaction_id}")
return f"REFUND-{transaction_id}"
# 尝试实例化抽象基类会失败
try:
base = PaymentProcessor()
except TypeError as e:
print(f"错误: {e}")
# 正确实例化子类
cc = CreditCardProcessor("M12345")
pp = PayPalProcessor("user@example.com")
# 使用支付处理器
cc.process_payment(100.50)
pp.process_payment(50.25)
# 退款
cc.refund("CC-M12345-100")
pp.refund("PP-user-50")
描述符协议
描述符是实现了描述符协议(__get__, __set__, __delete__)的类,用于自定义属性访问行为。
class TypedProperty:
"""描述符:确保属性值为特定类型"""
def __init__(self, name, expected_type):
self.name = name
self.expected_type = expected_type
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__.get(self.name)
def __set__(self, instance, value):
if not isinstance(value, self.expected_type):
raise TypeError(f"{self.name} 必须是 {self.expected_type.__name__} 类型")
instance.__dict__[self.name] = value
def __delete__(self, instance):
raise AttributeError(f"不能删除属性 {self.name}")
class Product:
# 使用描述符定义属性
name = TypedProperty("name", str)
price = TypedProperty("price", (int, float)) # 可以是int或float
quantity = TypedProperty("quantity", int)
def __init__(self, name, price, quantity):
self.name = name
self.price = price
self.quantity = quantity
def total_value(self):
return self.price * self.quantity
# 使用示例
try:
p = Product("Laptop", 999.99, 5)
print(f"产品: {p.name}, 单价: {p.price}, 数量: {p.quantity}")
print(f"总价值: {p.total_value()}")
# 尝试设置错误类型
p.price = "1000" # 会引发TypeError
except TypeError as e:
print(f"类型错误: {e}")
# 尝试删除属性
try:
del p.quantity
except AttributeError as e:
print(f"删除错误: {e}")
设计模式中的OOP应用
单例模式
确保一个类只有一个实例,并提供全局访问点。
import threading
class DatabaseConnection:
_instance = None
_lock = threading.Lock()
def __new__(cls, *args, **kwargs):
# 使用双重检查锁定实现线程安全的单例
if not cls._instance:
with cls._lock:
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, connection_string):
# 确保初始化只执行一次
if not hasattr(self, '_initialized'):
self.connection_string = connection_string
self.connection = None
self._initialized = True
def connect(self):
if not self.connection:
print(f"连接到数据库: {self.connection_string}")
self.connection = f"ConnectionObject({self.connection_string})"
return self.connection
def disconnect(self):
if self.connection:
print("断开数据库连接")
self.connection = None
# 测试单例模式
db1 = DatabaseConnection("mysql://localhost:3306/mydb")
db2 = DatabaseConnection("postgresql://localhost:5432/otherdb")
print(f"db1实例: {id(db1)}")
print(f"db2实例: {id(db2)}")
print(f"是否为同一实例: {db1 is db2}") # True
db1.connect()
db2.connect() # 不会创建新连接
# 在多线程环境中测试
def connect_db():
db = DatabaseConnection("mysql://localhost:3306/mydb")
db.connect()
threads = []
for _ in range(5):
t = threading.Thread(target=connect_db)
threads.append(t)
t.start()
for t in threads:
t.join()
观察者模式
定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖者都会收到通知。
class Subject:
"""主题(被观察者)"""
def __init__(self):
self._observers = []
self._state = None
def attach(self, observer):
"""添加观察者"""
if observer not in self._observers:
self._observers.append(observer)
def detach(self, observer):
"""移除观察者"""
try:
self._observers.remove(observer)
except ValueError:
pass
def notify(self):
"""通知所有观察者"""
for observer in self._observers:
observer.update(self)
@property
def state(self):
return self._state
@state.setter
def state(self, value):
self._state = value
self.notify() # 状态改变时通知观察者
class Observer:
"""观察者基类"""
def update(self, subject):
pass
class NewsAgency(Subject):
"""新闻机构(具体主题)"""
def __init__(self):
super().__init__()
self._news = None
@property
def news(self):
return self._news
@news.setter
def news(self, value):
self._news = value
self.state = f"新闻更新: {value}"
class Newspaper(Observer):
"""报纸(具体观察者)"""
def __init__(self, name):
self.name = name
def update(self, subject):
if isinstance(subject, NewsAgency):
print(f"{self.name} 收到新闻: {subject.news}")
class TVStation(Observer):
"""电视台(具体观察者)"""
def __init__(self, name):
self.name = name
def update(self, subject):
if isinstance(subject, NewsAgency):
print(f"{self.name} 正在报道: {subject.news}")
# 使用示例
agency = NewsAgency()
# 创建观察者
ny_times = Newspaper("纽约时报")
bbc = TVStation("BBC")
cnn = TVStation("CNN")
# 添加观察者
agency.attach(ny_times)
agency.attach(bbc)
agency.attach(cnn)
# 发布新闻
print("=== 发布第一条新闻 ===")
agency.news = "Python 3.12 发布了!"
# 移除一个观察者
agency.detach(bbc)
# 发布第二条新闻
print("\n=== 发布第二条新闻 ===")
agency.news = "人工智能领域取得新突破"
总结与最佳实践
面向对象设计原则
- 单一职责原则(SRP):一个类应该只有一个改变的理由
- 开闭原则(OCP):对扩展开放,对修改关闭
- 里氏替换原则(LSP):子类应该能够替换父类
- 接口隔离原则(ISP):客户端不应该被迫依赖它们不使用的接口
- 依赖倒置原则(DIP):依赖抽象而不是具体实现
Python OOP最佳实践
- 使用属性装饰器:优先使用
@property而不是直接暴露属性 - 合理使用继承:避免过深的继承层次,考虑组合优于继承
- 文档字符串:为类和方法编写清晰的文档
- 类型提示:使用类型注解提高代码可读性和可维护性
- 避免魔法方法滥用:只在有意义时使用特殊方法
- 保持类的简洁:遵循单一职责原则,避免过大的类
- 使用抽象基类定义接口:确保子类实现必要的方法
完整示例:综合应用
from abc import ABC, abstractmethod
from typing import List, Optional
from datetime import datetime
class Notification(ABC):
"""通知的抽象基类"""
@abstractmethod
def send(self, message: str) -> bool:
pass
class EmailNotification(Notification):
def __init__(self, email: str):
self.email = email
def send(self, message: str) -> bool:
print(f"发送邮件到 {self.email}: {message}")
return True
class SMSNotification(Notification):
def __init__(self, phone: str):
self.phone = phone
def send(self, message: str) -> bool:
print(f"发送短信到 {self.phone}: {message}")
return True
class User:
"""用户类"""
def __init__(self, username: str, email: str, phone: str):
self.username = username
self._email = email
self._phone = phone
self._notifications: List[Notification] = []
@property
def email(self) -> str:
return self._email
@email.setter
def email(self, value: str):
if "@" not in value:
raise ValueError("无效的邮箱格式")
self._email = value
@property
def phone(self) -> str:
return self._phone
@phone.setter
def phone(self, value: str):
if not value.isdigit() or len(value) < 10:
raise ValueError("无效的电话号码")
self._phone = value
def add_notification(self, notification: Notification):
self._notifications.append(notification)
def notify_all(self, message: str):
"""发送通知给所有渠道"""
for notification in self._notifications:
notification.send(message)
class Order:
"""订单类"""
def __init__(self, order_id: str, user: User, items: List[str]):
self.order_id = order_id
self.user = user
self.items = items
self.status = "pending"
self.created_at = datetime.now()
def process(self):
"""处理订单"""
self.status = "processing"
self.user.notify_all(f"订单 {self.order_id} 正在处理中")
def complete(self):
"""完成订单"""
self.status = "completed"
self.user.notify_all(f"订单 {self.order_id} 已完成")
def cancel(self):
"""取消订单"""
self.status = "cancelled"
self.user.notify_all(f"订单 {self.order_id} 已取消")
def __str__(self):
return (f"订单 {self.order_id} - 用户: {self.user.username}\n"
f"商品: {', '.join(self.items)}\n"
f"状态: {self.status}\n"
f"创建时间: {self.created_at.strftime('%Y-%m-%d %H:%M:%S')}")
# 使用示例
if __name__ == "__main__":
# 创建用户
user = User("john_doe", "john@example.com", "13800138000")
# 添加通知渠道
user.add_notification(EmailNotification(user.email))
user.add_notification(SMSNotification(user.phone))
# 创建订单
order = Order("ORD-2023-001", user, ["Python书籍", "键盘"])
# 处理订单
print("=== 创建订单 ===")
print(order)
print("\n=== 处理订单 ===")
order.process()
print("\n=== 完成订单 ===")
order.complete()
# 测试错误处理
try:
user.email = "invalid-email"
except ValueError as e:
print(f"\n错误捕获: {e}")
通过这个完整的示例,我们可以看到面向对象编程的各个方面的综合应用:抽象基类定义接口、属性封装、组合模式、事件通知等。这种设计使得代码结构清晰、易于扩展和维护。
结语
面向对象编程是Python的核心特性之一,掌握它对于编写高质量的Python代码至关重要。本文从基础概念到高级应用,详细介绍了Python OOP的各个方面。通过合理运用这些概念和技术,您可以创建出更加模块化、可重用和易于维护的代码。
记住,好的面向对象设计不仅仅是关于语法,更是关于如何将现实世界的问题域有效地映射到代码结构中。持续实践和学习,您将能够更加熟练地运用这些概念来解决复杂的编程问题。
