Python 面向对象高级特性
本文档介绍 Python 面向对象编程的高级特性和设计模式。
1. 元类编程
1.1 自定义元类
class MetaLogger(type):
def __new__(cls, name, bases, attrs):
# 为每个方法添加日志功能
for key, value in attrs.items():
if callable(value) and not key.startswith('__'):
attrs[key] = cls.log_decorator(value)
return super().__new__(cls, name, bases, attrs)
@staticmethod
def log_decorator(func):
def wrapper(*args, **kwargs):
print(f"调用方法: {func.__name__}")
result = func(*args, **kwargs)
print(f"方法返回: {result}")
return result
return wrapper
class MyClass(metaclass=MetaLogger):
def hello(self):
return "Hello, World!"
# 使用示例
obj = MyClass()
obj.hello() # 自动记录日志
1.2 抽象基类
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
"""计算面积"""
pass
@abstractmethod
def perimeter(self):
"""计算周长"""
pass
@property
@abstractmethod
def name(self):
"""形状名称"""
pass
class Circle(Shape):
def __init__(self, radius):
self._radius = radius
def area(self):
return 3.14 * self._radius ** 2
def perimeter(self):
return 2 * 3.14 * self._radius
@property
def name(self):
return "圆形"
2. 描述符
2.1 数据描述符
class TypedProperty:
def __init__(self, name, type_):
self.name = name
self.type_ = 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.type_):
raise TypeError(f"{self.name} 必须是 {self.type_} 类型")
instance.__dict__[self.name] = value
class Person:
name = TypedProperty('name', str)
age = TypedProperty('age', int)
def __init__(self, name, age):
self.name = name
self.age = age
# 使用示例
person = Person("张三", 25)
try:
person.age = "invalid" # 引发 TypeError
except TypeError as e:
print(e)
2.2 非数据描述符
class LazyProperty:
def __init__(self, func):
self.func = func
self.__doc__ = func.__doc__
def __get__(self, instance, owner):
if instance is None:
return self
value = self.func(instance)
setattr(instance, self.func.__name__, value)
return value
class Circle:
def __init__(self, radius):
self.radius = radius
@LazyProperty
def area(self):
print("计算面积...")
return 3.14 * self.radius ** 2
# 使用示例
circle = Circle(5)
print(circle.area) # 第一次计算
print(circle.area) # 直接返回缓存值
3. 设计模式
3.1 单例模式
class Singleton(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=Singleton):
def __init__(self):
print("初始化数据库连接...")
self.connected = True
def query(self, sql):
if self.connected:
return f"执行查询: {sql}"
# 使用示例
db1 = Database()
db2 = Database()
print(db1 is db2) # 输出: True
3.2 工厂模式
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "汪汪!"
class Cat(Animal):
def speak(self):
return "喵喵!"
class AnimalFactory:
@staticmethod
def create_animal(animal_type):
if animal_type == "dog":
return Dog()
elif animal_type == "cat":
return Cat()
raise ValueError("未知的动物类型")
# 使用示例
factory = AnimalFactory()
dog = factory.create_animal("dog")
cat = factory.create_animal("cat")
print(dog.speak()) # 输出: 汪汪!
print(cat.speak()) # 输出: 喵喵!
4. 高级特性
4.1 上下文管理器
class FileManager:
def __init__(self, filename, mode='r'):
self.filename = filename
self.mode = mode
self.file = None
def __enter__(self):
self.file = open(self.filename, self.mode)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
if exc_type is not None:
# 处理异常
print(f"发生异常: {exc_val}")
return True # 抑制异常
# 使用示例
with FileManager('test.txt', 'w') as f:
f.write('Hello, World!')
4.2 属性访问控制
class ProtectedAttributes:
def __init__(self):
self._internal = 0
def __getattribute__(self, name):
print(f"访问属性: {name}")
return super().__getattribute__(name)
def __setattr__(self, name, value):
print(f"设置属性: {name} = {value}")
super().__setattr__(name, value)
def __delattr__(self, name):
print(f"删除属性: {name}")
super().__delattr__(name)
# 使用示例
obj = ProtectedAttributes()
obj._internal = 42
print(obj._internal)
del obj._internal
5. 最佳实践
5.1 多重继承
class LoggerMixin:
def log(self, message):
print(f"[{self.__class__.__name__}] {message}")
class SaverMixin:
def save(self):
print(f"保存 {self.__class__.__name__} 的状态")
class User(LoggerMixin, SaverMixin):
def __init__(self, name):
self.name = name
def update(self):
self.log(f"更新用户: {self.name}")
self.save()
# 使用示例
user = User("张三")
user.update()
5.2 属性验证
class ValidatedProperty:
def __init__(self, validator):
self.validator = validator
self.name = None
def __set_name__(self, owner, name):
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):
if self.validator(value):
instance.__dict__[self.name] = value
else:
raise ValueError(f"Invalid value for {self.name}")
class User:
name = ValidatedProperty(lambda x: isinstance(x, str) and len(x) >= 3)
age = ValidatedProperty(lambda x: isinstance(x, int) and 0 <= x <= 150)
# 使用示例
user = User()
user.name = "张三" # 有效
try:
user.age = -1 # 无效
except ValueError:
print("年龄无效")
注意事项
- 元类编程要谨慎使用,避免过度复杂化
- 描述符应该是类级别的属性
- 单例模式要考虑线程安全问题
- 多重继承要注意方法解析顺序(MRO)
- 属性访问控制要考虑性能影响
最佳实践
- 优先使用组合而不是继承
- 使用描述符实现可重用的属性验证
- 合理使用混入类(Mixin)来增加功能
- 遵循开闭原则,对扩展开放,对修改关闭
- 使用抽象基类定义接口规范