预计阅读时间:39 分钟
Python 面向对象编程深度解析
一、面向对象的核心思想
面向对象编程(OOP)不是简单的语法糖,而是一种组织代码的思维方式。它通过将数据和操作数据的方法封装在一起,模拟现实世界的事物和它们之间的关系。
1.1 为什么需要面向对象?
# 面向过程的方式
def calculate_circle_area(radius):
return 3.14159 * radius * radius
def calculate_circle_perimeter(radius):
return 2 * 3.14159 * radius
radius1 = 5
radius2 = 10
area1 = calculate_circle_area(radius1)
perimeter1 = calculate_circle_perimeter(radius1)
# 面向对象的方式
class Circle:
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
circle1 = Circle(5)
circle2 = Circle(10)
print(f"圆1面积: {circle1.area()}, 周长: {circle1.perimeter()}")
print(f"圆2面积: {circle2.area()}, 周长: {circle2.perimeter()}")
# OOP的优势:
# 1. 数据和操作绑定在一起
# 2. 代码更容易理解和维护
# 3. 便于扩展和复用
1.2 三大核心特性
# 面向对象的三大支柱:
# 1. 封装 (Encapsulation) - 隐藏内部实现
# 2. 继承 (Inheritance) - 复用和扩展已有代码
# 3. 多态 (Polymorphism) - 统一接口,不同实现
class BankAccount:
"""封装示例:银行账户"""
def __init__(self, owner, initial_balance=0):
self.owner = owner
self.__balance = initial_balance # 私有属性(名称改编)
self._transaction_history = [] # 受保护属性(约定)
def deposit(self, amount):
"""存款(公有接口)"""
if amount <= 0:
raise ValueError("存款金额必须大于0")
self.__balance += amount
self._add_transaction(f"存款: +{amount}")
def withdraw(self, amount):
"""取款(公有接口)"""
if amount <= 0:
raise ValueError("取款金额必须大于0")
if amount > self.__balance:
raise ValueError("余额不足")
self.__balance -= amount
self._add_transaction(f"取款: -{amount}")
def get_balance(self):
"""查询余额(受控访问)"""
return self.__balance
def _add_transaction(self, description):
"""添加交易记录(内部使用)"""
from datetime import datetime
self._transaction_history.append({
'time': datetime.now(),
'description': description,
'balance': self.__balance
})
def get_history(self):
"""获取交易历史(只读副本)"""
return self._transaction_history.copy()
# 使用
account = BankAccount("Alice", 1000)
account.deposit(500)
account.withdraw(200)
print(f"余额: {account.get_balance()}")
# print(account.__balance) # AttributeError,无法直接访问
print(f"交易记录: {len(account.get_history())} 条")
二、类的定义与实例化
2.1 类的基本结构
class Person:
"""人类 - 展示类的完整结构"""
# 类属性(所有实例共享)
species = "Homo Sapiens"
count = 0
def __init__(self, name, age):
# 实例属性(每个实例独立)
self.name = name
self.age = age
self._created_at = self._get_current_time()
# 修改类属性
Person.count += 1
# 实例方法(最常用)
def introduce(self):
return f"我叫 {self.name},今年 {self.age} 岁"
# 类方法(操作类属性)
@classmethod
def get_count(cls):
return f"已创建 {cls.count} 个人"
@classmethod
def create_baby(cls, name):
"""工厂方法:创建婴儿"""
return cls(name, 0)
# 静态方法(工具函数)
@staticmethod
def _get_current_time():
from datetime import datetime
return datetime.now()
@staticmethod
def is_adult(age):
return age >= 18
# 特殊方法(魔术方法)
def __str__(self):
return f"Person({self.name}, {self.age})"
def __repr__(self):
return f"Person(name='{self.name}', age={self.age})"
def __eq__(self, other):
if not isinstance(other, Person):
return False
return self.name == other.name and self.age == other.age
def __lt__(self, other):
"""小于比较(用于排序)"""
return self.age < other.age
# 使用示例
person1 = Person("Alice", 25)
person2 = Person("Bob", 30)
baby = Person.create_baby("Charlie")
print(person1.introduce())
print(Person.get_count())
print(f"Alice 是成年人吗? {Person.is_adult(person1.age)}")
# 自动调用特殊方法
print(str(person1)) # __str__
print(repr(person1)) # __repr__
print(person1 == person2) # __eq__
people = [person2, person1]
print(sorted(people)) # __lt__ 实现排序
2.2 属性访问控制
class Temperature:
"""展示 Python 的属性访问控制"""
def __init__(self, celsius=0):
self._celsius = celsius # 受保护属性
self.__kelvin_offset = 273.15 # 私有属性
# 使用 property 装饰器
@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
@property
def kelvin(self):
"""开尔文(只读属性)"""
return self._celsius + self.__kelvin_offset
# 使用 property 函数(旧式方法)
def get_kelvin_offset(self):
return self.__kelvin_offset
kelvin_offset = property(get_kelvin_offset)
# 属性删除器
@celsius.deleter
def celsius(self):
del self._celsius
# 使用
temp = Temperature(25)
print(f"摄氏度: {temp.celsius}°C")
print(f"华氏度: {temp.fahrenheit}°F")
print(f"开尔文: {temp.kelvin}K")
temp.celsius = 30
print(f"新的华氏度: {temp.fahrenheit}°F")
temp.fahrenheit = 100
print(f"对应的摄氏度: {temp.celsius}°C")
# 访问私有属性(名称改编)
# print(temp.__kelvin_offset) # AttributeError
print(temp._Temperature__kelvin_offset) # 可以访问,但不推荐
2.3 类装饰器与元类初探
# 使用类装饰器增强类
def add_repr(cls):
"""为类添加 __repr__ 方法"""
def __repr__(self):
attrs = ', '.join(f"{k}={v!r}" for k, v in self.__dict__.items())
return f"{cls.__name__}({attrs})"
cls.__repr__ = __repr__
return cls
def add_str(cls):
"""为类添加 __str__ 方法"""
def __str__(self):
return f"{cls.__name__} 实例"
cls.__str__ = __str__
return cls
@add_repr
@add_str
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(3, 4)
print(p) # Point 实例
print(repr(p)) # Point(x=3, y=4)
# 使用 dataclass 简化类定义
from dataclasses import dataclass, field
from typing import List
@dataclass(order=True)
class Student:
sort_index: int = field(init=False, repr=False)
name: str
age: int
grades: List[float] = field(default_factory=list)
def __post_init__(self):
"""初始化后处理"""
self.sort_index = self.age
def average_grade(self):
if not self.grades:
return 0
return sum(self.grades) / len(self.grades)
student = Student("Alice", 20, [85, 90, 88])
print(student)
print(f"平均分: {student.average_grade():.1f}")
三、继承与多态
3.1 基础继承
class Animal:
"""动物基类"""
def __init__(self, name, age):
self.name = name
self.age = age
self._energy = 100
def eat(self, food):
"""吃食物恢复能量"""
self._energy += food.energy
return f"{self.name} 吃了 {food.name}"
def sleep(self):
"""睡觉恢复能量"""
self._energy = 100
return f"{self.name} 睡了一觉,精力充沛"
def make_sound(self):
"""发出声音(子类应该重写)"""
raise NotImplementedError("子类必须实现 make_sound 方法")
def get_status(self):
return f"{self.name} (能量: {self._energy})"
class Food:
"""食物类"""
def __init__(self, name, energy):
self.name = name
self.energy = energy
class Dog(Animal):
"""狗类 - 继承自 Animal"""
def __init__(self, name, age, breed="混血"):
# 调用父类初始化
super().__init__(name, age)
self.breed = breed
self._tricks = []
def make_sound(self):
"""重写父类方法"""
return f"{self.name}: 汪汪!"
def wag_tail(self):
"""狗特有的方法"""
return f"{self.name} 摇尾巴"
def learn_trick(self, trick):
"""学习新技能"""
self._tricks.append(trick)
return f"{self.name} 学会了 {trick}"
def perform_tricks(self):
"""表演所有技能"""
if not self._tricks:
return f"{self.name} 还不会任何技能"
tricks = ', '.join(self._tricks)
return f"{self.name} 表演: {tricks}"
def get_status(self):
"""扩展父类方法"""
base_status = super().get_status()
return f"{base_status}, 品种: {self.breed}"
class Cat(Animal):
"""猫类"""
def __init__(self, name, age, color="橘色"):
super().__init__(name, age)
self.color = color
self._mice_caught = 0
def make_sound(self):
return f"{self.name}: 喵喵~"
def catch_mouse(self):
"""猫特有的方法"""
self._mice_caught += 1
self._energy -= 10
return f"{self.name} 抓到了一只老鼠!总共抓到 {self._mice_caught} 只"
def purr(self):
return f"{self.name} 发出咕噜声"
# 使用
dog = Dog("旺财", 3, "金毛")
cat = Cat("咪咪", 2)
print(dog.make_sound())
print(cat.make_sound())
food = Food("狗粮", 20)
print(dog.eat(food))
print(dog.learn_trick("坐下"))
print(dog.learn_trick("握手"))
print(dog.perform_tricks())
print(cat.catch_mouse())
print(cat.purr())
# 多态:统一接口,不同实现
animals = [dog, cat]
for animal in animals:
print(f"{animal.name}: {animal.make_sound()}")
print(f" 状态: {animal.get_status()}")
3.2 多重继承与 MRO
class Flyable:
"""会飞的"""
def fly(self):
return f"{self.__class__.__name__} 在飞行"
def move(self):
return self.fly()
class Swimmable:
"""会游泳的"""
def swim(self):
return f"{self.__class__.__name__} 在游泳"
def move(self):
return self.swim()
class Walkable:
"""会行走的"""
def walk(self):
return f"{self.__class__.__name__} 在行走"
def move(self):
return self.walk()
# 多重继承
class Duck(Walkable, Swimmable, Flyable):
"""鸭子 - 继承自多个父类"""
def __init__(self, name):
self.name = name
def quack(self):
return f"{self.name}: 嘎嘎!"
# 重写 move 方法,结合多种能力
def move(self):
return f"{self.name} 可以走路、游泳和飞行"
class Penguin(Walkable, Swimmable):
"""企鹅 - 不会飞"""
def __init__(self, name):
self.name = name
def move(self):
return f"{self.name} 摇摇摆摆地走路,优雅地游泳"
# 查看方法解析顺序(MRO)
print("Duck MRO:", [cls.__name__ for cls in Duck.__mro__])
print("Penguin MRO:", [cls.__name__ for cls in Penguin.__mro__])
duck = Duck("唐老鸭")
penguin = Penguin("企鹅")
print(duck.quack())
print(duck.walk())
print(duck.swim())
print(duck.fly())
print(duck.move())
print(penguin.walk())
print(penguin.swim())
# print(penguin.fly()) # AttributeError,Penguin 没有 fly 方法
# 菱形继承问题
class A:
def method(self):
return "A.method"
def call(self):
return "A.call"
class B(A):
def method(self):
return "B.method"
def call(self):
return f"B.call -> {super().call()}"
class C(A):
def method(self):
return "C.method"
def call(self):
return f"C.call -> {super().call()}"
class D(B, C):
def method(self):
return f"D.method -> {super().method()}"
# MRO 确保每个父类只调用一次
print("D MRO:", [cls.__name__ for cls in D.__mro__])
d = D()
print(d.method())
print(d.call()) # 协作式多重继承
3.3 抽象基类
from abc import ABC, abstractmethod
import math
class Shape(ABC):
"""形状抽象基类"""
def __init__(self, name):
self.name = name
@abstractmethod
def area(self):
"""计算面积 - 子类必须实现"""
pass
@abstractmethod
def perimeter(self):
"""计算周长 - 子类必须实现"""
pass
def describe(self):
"""具体方法(子类可选重写)"""
return f"{self.name}: 面积={self.area():.2f}, 周长={self.perimeter():.2f}"
@classmethod
def __subclasshook__(cls, subclass):
"""自定义子类检查(鸭子类型)"""
if cls is Shape:
required_methods = ['area', 'perimeter']
if all(hasattr(subclass, method) for method in required_methods):
return True
return NotImplemented
class Circle(Shape):
"""圆形"""
def __init__(self, radius):
super().__init__("圆形")
self.radius = radius
def area(self):
return math.pi * self.radius ** 2
def perimeter(self):
return 2 * math.pi * self.radius
def diameter(self):
"""圆形特有的方法"""
return 2 * self.radius
class Rectangle(Shape):
"""矩形"""
def __init__(self, width, height):
super().__init__("矩形")
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
@property
def is_square(self):
"""是否为正方形"""
return self.width == self.height
class Triangle(Shape):
"""三角形"""
def __init__(self, a, b, c):
super().__init__("三角形")
self.a = a
self.b = b
self.c = c
# 验证是否为有效三角形
if not self._is_valid():
raise ValueError("无效的三角形边长")
def _is_valid(self):
"""检查是否为有效三角形"""
return (self.a + self.b > self.c and
self.b + self.c > self.a and
self.c + self.a > self.b)
def area(self):
# 海伦公式
s = self.perimeter() / 2
return math.sqrt(s * (s - self.a) * (s - self.b) * (s - self.c))
def perimeter(self):
return self.a + self.b + self.c
# 使用抽象基类
shapes = [
Circle(5),
Rectangle(4, 6),
Triangle(3, 4, 5)
]
for shape in shapes:
print(shape.describe())
if isinstance(shape, Circle):
print(f" 直径: {shape.diameter():.2f}")
elif isinstance(shape, Rectangle):
print(f" 是正方形吗? {shape.is_square}")
# 鸭子类型:只要实现了 area 和 perimeter,就可以被识别为 Shape
class House:
"""一个实现了面积和周长的类,但不是 Shape 的子类"""
def __init__(self, length, width):
self.length = length
self.width = width
def area(self):
return self.length * self.width
def perimeter(self):
return 2 * (self.length + self.width)
house = House(10, 8)
print(f"House 是 Shape 的子类吗? {issubclass(House, Shape)}") # True(因为 __subclasshook__)
print(f"房子的 {house.area()} 平方米")
四、高级面向对象特性
4.1 描述符(Descriptor)
class Validator:
"""描述符基类"""
def __init__(self, name=None):
self.name = name
def __set_name__(self, owner, name):
"""Python 3.6+ 自动调用,设置属性名"""
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__.get(self.name)
def __set__(self, instance, value):
self.validate(value)
instance.__dict__[self.name] = value
def validate(self, value):
"""子类应该重写此方法"""
pass
class PositiveNumber(Validator):
"""正数验证器"""
def validate(self, value):
if value <= 0:
raise ValueError(f"{self.name} 必须是正数")
return value
class StringLength(Validator):
"""字符串长度验证器"""
def __init__(self, min_len=1, max_len=None):
super().__init__()
self.min_len = min_len
self.max_len = max_len
def validate(self, value):
if not isinstance(value, str):
raise TypeError(f"{self.name} 必须是字符串")
if len(value) < self.min_len:
raise ValueError(f"{self.name} 长度至少为 {self.min_len}")
if self.max_len and len(value) > self.max_len:
raise ValueError(f"{self.name} 长度最多为 {self.max_len}")
return value
class Email(Validator):
"""邮箱验证器"""
def validate(self, value):
if not isinstance(value, str):
raise TypeError("邮箱必须是字符串")
if '@' not in value or '.' not in value:
raise ValueError(f"无效的邮箱格式: {value}")
return value
class Typed(Validator):
"""类型验证器"""
def __init__(self, expected_type):
super().__init__()
self.expected_type = expected_type
def validate(self, value):
if not isinstance(value, self.expected_type):
raise TypeError(f"{self.name} 必须是 {self.expected_type.__name__} 类型")
return value
# 使用描述符
class Product:
"""产品类 - 使用描述符进行验证"""
name = StringLength(min_len=2, max_len=50)
price = PositiveNumber()
quantity = PositiveNumber()
description = StringLength(min_len=10)
def __init__(self, name, price, quantity, description=""):
self.name = name
self.price = price
self.quantity = quantity
self.description = description or f"{name} 的产品描述,非常优质"
@property
def total_value(self):
return self.price * self.quantity
def __str__(self):
return f"{self.name} (价格: ¥{self.price}, 库存: {self.quantity})"
class User:
"""用户类"""
username = StringLength(min_len=3, max_len=20)
email = Email()
age = PositiveNumber()
def __init__(self, username, email, age):
self.username = username
self.email = email
self.age = age
# 测试
try:
product = Product("笔记本电脑", 5999, 10, "高性能笔记本电脑,适合办公和游戏")
print(product)
print(f"总价值: ¥{product.total_value}")
user = User("alice", "alice@example.com", 25)
print(f"用户: {user.username}, 邮箱: {user.email}")
# 触发验证错误
product.price = -100 # ValueError
except (ValueError, TypeError) as e:
print(f"验证错误: {e}")
4.2 元类(Metaclass)
# 元类是类的类,控制类的创建过程
# 1. 使用 type 动态创建类
def say_hello(self):
return f"Hello from {self.name}"
# 动态创建类
DynamicClass = type('DynamicClass', (object,), {
'name': 'Dynamic',
'say_hello': say_hello,
'__str__': lambda self: f"DynamicClass({self.name})"
})
obj = DynamicClass()
print(obj.say_hello())
# 2. 自定义元类
class SingletonMeta(type):
"""单例模式元类"""
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class Database(metaclass=SingletonMeta):
"""数据库连接单例"""
def __init__(self, host='localhost', port=3306):
self.host = host
self.port = port
self.connected = False
print(f"初始化数据库连接: {host}:{port}")
def connect(self):
self.connected = True
return f"已连接到 {self.host}:{self.port}"
def query(self, sql):
if not self.connected:
self.connect()
return f"执行查询: {sql}"
# 测试单例
db1 = Database('db1.example.com', 3306)
db2 = Database('db2.example.com', 5432)
print(db1 is db2) # True
print(db1.host) # db1.example.com(第一次初始化的参数)
# 3. 验证类的元类
class ValidateFieldsMeta(type):
"""验证类属性的元类"""
def __new__(mcs, name, bases, namespace):
# 检查是否有 required_fields 属性
if 'required_fields' in namespace:
required = namespace['required_fields']
for field in required:
if field not in namespace:
raise TypeError(f"类 {name} 缺少必需字段: {field}")
# 自动添加创建时间戳
from datetime import datetime
namespace['created_at'] = datetime.now()
return super().__new__(mcs, name, bases, namespace)
class APIModel(metaclass=ValidateFieldsMeta):
"""API 模型基类"""
required_fields = ['table_name']
table_name = 'default_table'
@classmethod
def get_table_name(cls):
return cls.table_name
# 正常定义
class UserModel(APIModel):
table_name = 'users'
fields = ['id', 'name', 'email']
print(f"UserModel 表名: {UserModel.get_table_name()}")
print(f"创建时间: {UserModel.created_at}")
# 错误定义
# class InvalidModel(APIModel):
# pass # TypeError: 类 InvalidModel 缺少必需字段: table_name
# 4. 自动注册的元类
class AutoRegisterMeta(type):
"""自动注册子类的元类"""
registry = {}
def __new__(mcs, name, bases, namespace):
cls = super().__new__(mcs, name, bases, namespace)
# 只注册非抽象类
if not namespace.get('abstract', False):
mcs.registry[name.lower()] = cls
return cls
@classmethod
def get_class(mcs, name):
"""根据名称获取类"""
return mcs.registry.get(name.lower())
class Plugin(metaclass=AutoRegisterMeta):
"""插件基类"""
abstract = True # 抽象类,不注册
def execute(self):
raise NotImplementedError
class ImagePlugin(Plugin):
"""图片处理插件"""
def execute(self):
return "处理图片"
class VideoPlugin(Plugin):
"""视频处理插件"""
def execute(self):
return "处理视频"
class AudioPlugin(Plugin):
"""音频处理插件"""
def execute(self):
return "处理音频"
# 使用自动注册
print("已注册的插件:", list(AutoRegisterMeta.registry.keys()))
# 根据名称动态创建实例
plugin_name = 'imageplugin'
plugin_class = AutoRegisterMeta.get_class(plugin_name)
if plugin_class:
plugin = plugin_class()
print(plugin.execute())
4.3 混入类(Mixin)
class SerializerMixin:
"""序列化混入"""
def to_dict(self):
"""转换为字典"""
result = {}
for key, value in self.__dict__.items():
# 跳过私有属性
if key.startswith('_'):
continue
# 处理嵌套对象
if hasattr(value, 'to_dict'):
result[key] = value.to_dict()
elif isinstance(value, (list, tuple)):
result[key] = [
item.to_dict() if hasattr(item, 'to_dict') else item
for item in value
]
else:
result[key] = value
return result
def to_json(self):
"""转换为 JSON"""
import json
return json.dumps(self.to_dict(), ensure_ascii=False, default=str)
class TimestampMixin:
"""时间戳混入"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
from datetime import datetime
self.created_at = datetime.now()
self.updated_at = datetime.now()
def update_timestamp(self):
from datetime import datetime
self.updated_at = datetime.now()
class LoggingMixin:
"""日志混入"""
def log(self, message, level='INFO'):
from datetime import datetime
timestamp = datetime.now().isoformat()
print(f"[{timestamp}] [{level}] {self.__class__.__name__}: {message}")
class ValidatableMixin:
"""验证混入"""
def validate(self):
"""验证对象,子类应定义 _validate 方法"""
if hasattr(self, '_validate'):
return self._validate()
return True
def is_valid(self):
try:
return self.validate()
except Exception:
return False
# 组合使用多个混入
class BlogPost(SerializerMixin, TimestampMixin, LoggingMixin, ValidatableMixin):
"""博客文章 - 组合多个混入"""
def __init__(self, title, content, author):
# 注意:需要调用所有父类的 __init__
super().__init__()
self.title = title
self.content = content
self.author = author
self.comments = []
self.published = False
self.log(f"创建文章: {title}")
def publish(self):
self.published = True
self.update_timestamp()
self.log(f"发布文章: {self.title}")
def add_comment(self, comment):
self.comments.append(comment)
self.update_timestamp()
self.log(f"添加评论: {comment.author}")
def _validate(self):
"""自定义验证逻辑"""
if not self.title:
raise ValueError("标题不能为空")
if len(self.title) > 200:
raise ValueError("标题不能超过200字符")
if not self.content:
raise ValueError("内容不能为空")
return True
class Comment(SerializerMixin, TimestampMixin):
"""评论类"""
def __init__(self, author, text):
super().__init__()
self.author = author
self.text = text
# 使用
post = BlogPost("Python 混入类", "混入是一种优雅的代码复用方式...", "Alice")
post.publish()
comment1 = Comment("Bob", "好文章!")
comment2 = Comment("Charlie", "学到了新知识")
post.add_comment(comment1)
post.add_comment(comment2)
# 序列化
print("\n文章字典:")
print(post.to_dict())
print("\n文章 JSON:")
print(post.to_json()[:200] + "...")
# 验证
print(f"\n文章有效吗? {post.is_valid()}")
五、设计模式实战
5.1 工厂模式
from abc import ABC, abstractmethod
from typing import Dict, Type
# 简单工厂
class Vehicle(ABC):
"""交通工具抽象类"""
@abstractmethod
def drive(self):
pass
@abstractmethod
def get_capacity(self):
pass
class Car(Vehicle):
def __init__(self, model):
self.model = model
def drive(self):
return f"驾驶汽车 {self.model}"
def get_capacity(self):
return 5
class Bike(Vehicle):
def __init__(self, model):
self.model = model
def drive(self):
return f"骑自行车 {self.model}"
def get_capacity(self):
return 1
class Bus(Vehicle):
def __init__(self, model):
self.model = model
def drive(self):
return f"驾驶公交车 {self.model}"
def get_capacity(self):
return 40
class VehicleFactory:
"""简单工厂"""
@staticmethod
def create_vehicle(vehicle_type: str, model: str) -> Vehicle:
if vehicle_type == 'car':
return Car(model)
elif vehicle_type == 'bike':
return Bike(model)
elif vehicle_type == 'bus':
return Bus(model)
else:
raise ValueError(f"未知的交通工具类型: {vehicle_type}")
# 工厂方法模式
class LogisticsApp(ABC):
"""物流应用(工厂方法)"""
@abstractmethod
def create_vehicle(self) -> Vehicle:
"""工厂方法"""
pass
def plan_delivery(self, distance):
vehicle = self.create_vehicle()
return f"使用 {vehicle.get_capacity()} 座位的交通工具,配送 {distance} 公里"
class UrbanLogistics(LogisticsApp):
"""城市物流"""
def create_vehicle(self):
return Bike("城市自行车")
class SuburbanLogistics(LogisticsApp):
"""郊区物流"""
def create_vehicle(self):
return Car("厢式货车")
class LongHaulLogistics(LogisticsApp):
"""长途物流"""
def create_vehicle(self):
return Bus("长途巴士")
# 抽象工厂模式
class VehiclePartsFactory(ABC):
"""车辆零件工厂(抽象工厂)"""
@abstractmethod
def create_engine(self):
pass
@abstractmethod
def create_wheel(self):
pass
class SportsCarPartsFactory(VehiclePartsFactory):
"""跑车零件工厂"""
def create_engine(self):
return "V8 发动机"
def create_wheel(self):
return "赛车轮胎"
class EconomyCarPartsFactory(VehiclePartsFactory):
"""经济型车零件工厂"""
def create_engine(self):
return "1.5L 发动机"
def create_wheel(self):
return "经济型轮胎"
class VehicleAssembler:
"""车辆装配器"""
def __init__(self, parts_factory: VehiclePartsFactory):
self.parts_factory = parts_factory
def assemble(self):
engine = self.parts_factory.create_engine()
wheel = self.parts_factory.create_wheel()
return f"装配完成:{engine} + {wheel}"
# 注册工厂(更灵活)
class RegisteredFactory:
"""注册工厂"""
_registry: Dict[str, Type] = {}
@classmethod
def register(cls, name: str):
"""注册装饰器"""
def decorator(target_class):
cls._registry[name] = target_class
return target_class
return decorator
@classmethod
def create(cls, name: str, **kwargs):
"""创建实例"""
if name not in cls._registry:
raise ValueError(f"未注册的类型: {name}")
return cls._registry[name](**kwargs)
@RegisteredFactory.register('electric_car')
class ElectricCar(Vehicle):
def __init__(self, model, battery_capacity=75):
self.model = model
self.battery_capacity = battery_capacity
def drive(self):
return f"静音驾驶 {self.model} (电量: {self.battery_capacity}kWh)"
def get_capacity(self):
return 5
# 测试
print("=== 简单工厂 ===")
car = VehicleFactory.create_vehicle('car', 'Tesla Model 3')
print(car.drive())
print("\n=== 工厂方法 ===")
urban = UrbanLogistics()
print(urban.plan_delivery(5))
print("\n=== 抽象工厂 ===")
sports_assembler = VehicleAssembler(SportsCarPartsFactory())
print(sports_assembler.assemble())
print("\n=== 注册工厂 ===")
electric = RegisteredFactory.create('electric_car', model='Tesla Model S', battery_capacity=100)
print(electric.drive())
5.2 建造者模式
class Computer:
"""计算机产品"""
def __init__(self):
self.cpu = None
self.ram = None
self.storage = None
self.gpu = None
self.os = None
def __str__(self):
specs = []
if self.cpu:
specs.append(f"CPU: {self.cpu}")
if self.ram:
specs.append(f"RAM: {self.ram}")
if self.storage:
specs.append(f"存储: {self.storage}")
if self.gpu:
specs.append(f"GPU: {self.gpu}")
if self.os:
specs.append(f"系统: {self.os}")
return "计算机配置:\n " + "\n ".join(specs)
class ComputerBuilder:
"""计算机建造者"""
def __init__(self):
self.computer = Computer()
def set_cpu(self, cpu):
self.computer.cpu = cpu
return self
def set_ram(self, ram):
self.computer.ram = ram
return self
def set_storage(self, storage):
self.computer.storage = storage
return self
def set_gpu(self, gpu):
self.computer.gpu = gpu
return self
def set_os(self, os):
self.computer.os = os
return self
def build(self):
return self.computer
class GamingComputerDirector:
"""游戏电脑指导者"""
@staticmethod
def construct(builder: ComputerBuilder):
return (builder
.set_cpu("Intel i9-13900K")
.set_ram("32GB DDR5")
.set_storage("2TB NVMe SSD")
.set_gpu("NVIDIA RTX 4090")
.set_os("Windows 11 Pro")
.build())
class OfficeComputerDirector:
"""办公电脑指导者"""
@staticmethod
def construct(builder: ComputerBuilder):
return (builder
.set_cpu("Intel i5-13400")
.set_ram("16GB DDR4")
.set_storage("512GB SSD")
.set_gpu("集成显卡")
.set_os("Windows 11 Home")
.build())
# 使用建造者模式
builder = ComputerBuilder()
# 方式1:使用指导者
gaming_pc = GamingComputerDirector.construct(builder)
print("游戏电脑:")
print(gaming_pc)
# 方式2:自定义配置
builder = ComputerBuilder()
custom_pc = (builder
.set_cpu("AMD Ryzen 7")
.set_ram("32GB DDR5")
.set_storage("1TB SSD + 2TB HDD")
.set_os("Ubuntu 22.04")
.build())
print("\n自定义电脑:")
print(custom_pc)
5.3 观察者模式
from abc import ABC, abstractmethod
from typing import List, Any
class Observer(ABC):
"""观察者接口"""
@abstractmethod
def update(self, subject: 'Subject', message: Any):
pass
class Subject(ABC):
"""主题(被观察者)接口"""
def __init__(self):
self._observers: List[Observer] = []
self._state = None
def attach(self, observer: Observer):
"""添加观察者"""
if observer not in self._observers:
self._observers.append(observer)
def detach(self, observer: Observer):
"""移除观察者"""
self._observers.remove(observer)
def notify(self, message: Any = None):
"""通知所有观察者"""
for observer in self._observers:
observer.update(self, message)
@property
def state(self):
return self._state
@state.setter
def state(self, value):
self._state = value
self.notify(f"状态改变为: {value}")
# 具体实现
class NewsAgency(Subject):
"""新闻机构(被观察者)"""
def __init__(self, name):
super().__init__()
self.name = name
self.news = []
def publish_news(self, title, content):
"""发布新闻"""
news_item = {
'title': title,
'content': content,
'agency': self.name
}
self.news.append(news_item)
self.notify(news_item)
return f"新闻已发布: {title}"
class EmailSubscriber(Observer):
"""邮件订阅者"""
def __init__(self, email):
self.email = email
def update(self, subject, message):
if isinstance(message, dict):
print(f"[邮件] 发送到 {self.email}: {message['title']} - 来自 {message['agency']}")
class SMSSubscriber(Observer):
"""短信订阅者"""
def __init__(self, phone):
self.phone = phone
def update(self, subject, message):
if isinstance(message, dict):
print(f"[短信] 发送到 {self.phone}: {message['title']}")
class LoggerSubscriber(Observer):
"""日志订阅者"""
def update(self, subject, message):
from datetime import datetime
timestamp = datetime.now().isoformat()
print(f"[日志 {timestamp}] 收到更新: {message}")
class DisplaySubscriber(Observer):
"""显示订阅者"""
def __init__(self, display_name):
self.display_name = display_name
self.latest_news = None
def update(self, subject, message):
self.latest_news = message
if isinstance(message, dict):
print(f"[显示板 {self.display_name}] 最新新闻: {message['title']}")
# 使用观察者模式
print("=== 观察者模式示例 ===")
# 创建新闻机构
bbc = NewsAgency("BBC News")
# 创建订阅者
email_sub = EmailSubscriber("user@example.com")
sms_sub = SMSSubscriber("+1234567890")
logger_sub = LoggerSubscriber()
display = DisplaySubscriber("时代广场大屏幕")
# 订阅
bbc.attach(email_sub)
bbc.attach(sms_sub)
bbc.attach(logger_sub)
bbc.attach(display)
# 发布新闻
bbc.publish_news("Python 3.13 发布", "新版本带来了更好的性能...")
print()
bbc.publish_news("AI 技术突破", "新一代语言模型展现出惊人能力...")
# 取消订阅
bbc.detach(sms_sub)
print("\n取消短信订阅后:")
bbc.publish_news("天气更新", "今天天气晴朗...")
六、最佳实践与性能优化
6.1 类设计原则
"""
面向对象设计原则(SOLID):
1. 单一职责原则 (SRP) - 一个类只负责一件事
2. 开闭原则 (OCP) - 对扩展开放,对修改封闭
3. 里氏替换原则 (LSP) - 子类可以替换父类
4. 接口隔离原则 (ISP) - 接口应该小而专一
5. 依赖倒置原则 (DIP) - 依赖抽象而非具体
"""
# 违反单一职责
class BadUserManager:
"""违反 SRP:既管理用户又发送邮件"""
def create_user(self, name, email):
# 创建用户
user = {'name': name, 'email': email}
# 保存到数据库
self.save_to_db(user)
# 发送欢迎邮件
self.send_welcome_email(email)
return user
def save_to_db(self, user):
print(f"保存用户到数据库: {user}")
def send_welcome_email(self, email):
print(f"发送欢迎邮件到: {email}")
# 遵循单一职责
class User:
"""用户实体"""
def __init__(self, name, email):
self.name = name
self.email = email
class UserRepository:
"""用户仓储"""
def save(self, user):
print(f"保存用户: {user.name}")
return user
class EmailService:
"""邮件服务"""
def send_welcome(self, email):
print(f"发送欢迎邮件到: {email}")
class UserService:
"""用户服务(协调者)"""
def __init__(self, repository, email_service):
self.repository = repository
self.email_service = email_service
def register(self, name, email):
user = User(name, email)
self.repository.save(user)
self.email_service.send_welcome(email)
return user
# 开闭原则示例
class DiscountStrategy(ABC):
"""折扣策略(抽象)"""
@abstractmethod
def calculate(self, price):
pass
class NoDiscount(DiscountStrategy):
def calculate(self, price):
return price
class PercentageDiscount(DiscountStrategy):
def __init__(self, percentage):
self.percentage = percentage
def calculate(self, price):
return price * (1 - self.percentage / 100)
class FixedDiscount(DiscountStrategy):
def __init__(self, amount):
self.amount = amount
def calculate(self, price):
return max(0, price - self.amount)
class Product:
"""产品类 - 对扩展开放"""
def __init__(self, name, price, discount_strategy=None):
self.name = name
self.price = price
self.discount_strategy = discount_strategy or NoDiscount()
def get_final_price(self):
return self.discount_strategy.calculate(self.price)
# 使用
product1 = Product("书", 100, PercentageDiscount(20))
product2 = Product("电子产品", 1000, FixedDiscount(100))
print(f"{product1.name}: ¥{product1.get_final_price()}")
print(f"{product2.name}: ¥{product2.get_final_price()}")
6.2 性能优化技巧
import timeit
from functools import lru_cache
class PerformanceOptimized:
"""展示性能优化技巧的类"""
# 1. 使用 __slots__ 减少内存占用
__slots__ = ['name', 'age', '_cache']
def __init__(self, name, age):
self.name = name
self.age = age
self._cache = {}
# 2. 缓存计算结果
def expensive_method(self, n):
"""耗时计算(带缓存)"""
if n in self._cache:
return self._cache[n]
# 模拟耗时计算
result = sum(i * i for i in range(n))
self._cache[n] = result
return result
# 3. 使用 @property 缓存
@property
@lru_cache(maxsize=1)
def complex_property(self):
"""计算属性(全局缓存)"""
print("计算复杂属性...")
import time
time.sleep(1) # 模拟耗时操作
return self.age * 2
# 比较 __slots__ 的内存优势
class NormalClass:
def __init__(self, name, age):
self.name = name
self.age = age
class SlotsClass:
__slots__ = ['name', 'age']
def __init__(self, name, age):
self.name = name
self.age = age
# 内存对比
import sys
normal_obj = NormalClass("Alice", 25)
slots_obj = SlotsClass("Alice", 25)
print(f"普通类内存: {sys.getsizeof(normal_obj.__dict__)} 字节")
# SlotsClass 没有 __dict__,节省内存
print(f"__slots__ 类内存: {sys.getsizeof(slots_obj)} 字节")
# 方法调用优化
class MethodOptimization:
"""方法调用优化"""
def __init__(self):
self.data = list(range(1000))
def normal_method(self):
"""普通方法"""
return sum(self.data)
# 将频繁调用的方法缓存为局部变量
def optimized_loop(self):
data = self.data # 局部变量访问更快
total = 0
for x in data:
total += x
return total
# 惰性初始化
class LazyInitialization:
"""惰性初始化"""
def __init__(self):
self._heavy_resource = None
@property
def heavy_resource(self):
"""只在需要时初始化"""
if self._heavy_resource is None:
print("初始化重量级资源...")
self._heavy_resource = self._create_heavy_resource()
return self._heavy_resource
def _create_heavy_resource(self):
"""创建重量级资源"""
import time
time.sleep(0.1) # 模拟耗时
return ["resource"] * 1000
lazy = LazyInitialization()
print("对象已创建,但资源未初始化")
_ = lazy.heavy_resource # 这里才真正初始化
print("资源已初始化")
七、总结
面向对象编程是 Python 的核心范式之一,掌握它能够让你写出更优雅、更易维护的代码。
核心要点回顾:
- 封装 - 隐藏实现细节,提供清晰的接口
- 使用
_和__约定 -
通过
@property控制属性访问 -
继承 - 代码复用和层次化设计
- 理解 MRO(方法解析顺序)
- 使用
super()正确调用父类方法 -
多重继承需谨慎
-
多态 - 统一接口,不同实现
- 鸭子类型(Duck Typing)
-
抽象基类(ABC)
-
高级特性
- 描述符:控制属性访问
- 元类:控制类的创建
-
混入类:灵活的代码复用
-
设计原则
- SOLID 原则
- 组合优于继承
- 面向接口编程
选择建议: - 简单场景 → 数据类(dataclass)或命名元组 - 需要验证 → 使用描述符或 property - 复杂行为 → 完整的类设计 - 插件系统 → 元类或注册模式
面向对象不是银弹,但在合适的场景下,它能让你的代码更加模块化、可测试和可维护。最重要的是理解其背后的设计思想,而不是简单地堆砌语法。
本文由 尚先生 原创,转载请注明出处。
评论
0