目录

元类的工作原理
元类是用来创建类的“类”,它控制类的创建过程。默认情况下,Python中所有类的元类是type。
通过自定义元类,可以在类创建时动态修改类的属性、方法,甚至控制类的继承行为。
类也是对象,在python里一切皆是对象,包括类本身
类也是类
def explore_class_as_object():
"""探索类作为对象的特性"""
class MyClass:
def __init__(self, value):
self.value = value
def method(self):
return f"Value is {self.value}"
print("=== 类也是对象 ===")
print(f"MyClass的类型: {type(MyClass)}") #<class 'type'>
print(f"MyClass是否是对象: {isinstance(MyClass, object)}") #True
print(f"MyClass的ID: {id(MyClass)}")
print(f"MyClass的属性: {dir(MyClass)}")
# 类可以像对象一样被操作
print(f"类的名称: {MyClass.__name__}") #类的名称: MyClass
print(f"类的模块: {MyClass.__module__}") #类的模块: __main__
print(f"类的基类: {MyClass.__bases__}") #类的基类: (<class 'object'>,)
# 甚至可以给类动态添加属性
MyClass.class_variable = "I'm a class variable"
print(f"动态添加的属性: {MyClass.class_variable}") #动态添加的属性: I'm a class variable
return MyClass
explore_class_as_object()
元类的创建过程
import time
class MetaclassDemo:
"""演示元类的创建过程"""
@staticmethod
def manual_class_creation():
"""手动创建类的过程"""
print("=== 手动类创建过程 ===")
# 步骤1: 准备类的命名空间
def init_method(self, value):
self.value = value
def str_method(self):
return f"ManualClass(value={self.value})"
# 步骤2: 创建类的字典
class_dict = {
'__init__': init_method,
'__str__': str_method,
'class_var': 'I am manually created'
}
# 步骤3: 使用type()创建类
ManualClass = type('ManualClass', (object,), class_dict)
print(f"手动创建的类: {ManualClass}")
print(f"类的名称: {ManualClass.__name__}")
print(f"类的基类: {ManualClass.__bases__}")
# 测试创建的类
instance = ManualClass("test_value")
print(f"实例: {instance}")
print(f"实例的值: {instance.value}")
return ManualClass
@staticmethod
def demonstrate_class_creation_hooks():
"""演示类创建的钩子方法"""
class TrackedMeta(type):
"""跟踪类创建过程的元类"""
def __new__(mcs, name, bases, namespace, **kwargs):
print(f" 创建类 {name}")
print(f" 基类: {bases}")
print(f" 命名空间键: {list(namespace.keys())}")
print(f" 额外参数: {kwargs}")
# 在类创建前修改命名空间
namespace['_created_by'] = 'TrackedMeta'
namespace['_creation_time'] = time.time()
# 调用父类的__new__创建类
cls = super().__new__(mcs, name, bases, namespace)
print(f" 类 {name} 创建完成")
return cls
def __init__(cls, name, bases, namespace, **kwargs):
print(f" 初始化类 {name}")
super().__init__(name, bases, namespace)
# 类创建后的初始化工作
cls._instances = []
def __call__(cls, *args, **kwargs):
print(f" 创建 {cls.__name__} 的实例")
instance = super().__call__(*args, **kwargs)
cls._instances.append(instance)
return instance
print("\n=== 类创建钩子演示 ===")
class TrackedClass(metaclass=TrackedMeta, custom_param="test"):
def __init__(self, name):
self.name = name
def __str__(self):
return f"TrackedClass({self.name})"
print(f"\n创建的类信息:")
print(f" 创建者: {TrackedClass._created_by}")
print(f" 创建时间: {TrackedClass._creation_time}")
# 创建实例
instance1 = TrackedClass("Alice")
instance2 = TrackedClass("Bob")
print(f"实例列表: {TrackedClass._instances}")
return TrackedClass
# 测试元类演示
demo = MetaclassDemo()
manual_class = demo.manual_class_creation()
tracked_class = demo.demonstrate_class_creation_hooks()
手动创建类的过程:
通过内置函数type(),可以手动创建一个类:1:准备类的命名空间,定义类的方法(如__init__和__str__)。2:构造类的字典,将方法和属性放入字典中。3:调用type()函数,传入类名、基类元组和类字典,动态生成类。
元类的钩子方法详解:
自定义元类继承自type,重写以下三个关键方法,控制类的创建和实例化流程:
1、 __new__(mcs, name, bases, namespace, **kwargs):类创建的第一步,负责构造类对象。可以在这里修改类的命名空间(如添加属性_created_by、_creation_time)调用super().__new__()完成类的真正创建。适合做类属性的自动注入、注册等操作。
2、 __init__(cls, name, bases, namespace, **kwargs):类创建完成后的初始化阶段。可以初始化类级别的状态(如示例中初始化_instances列表用于跟踪实例)。这里的cls是新创建的类对象。
3、__call__(cls, *args, **kwargs):控制类的实例化过程。在调用类创建实例时触发。可以在这里添加实例创建的日志、缓存或统计功能。示例中将所有实例保存到_instances列表,方便后续管理。
实用元类
class UtilityMetaclasses:
"""实用的元类模式集合"""
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 ValidatedMeta(type):
"""属性验证元类"""
def __new__(mcs, name, bases, namespace):
# 收集所有需要验证的属性
validators = {}
for key, value in namespace.items():
if hasattr(value, '_validator'):
validators[key] = value._validator
namespace['_validators'] = validators
# 重写__setattr__以支持验证
original_setattr = namespace.get('__setattr__', object.__setattr__)
def validated_setattr(self, name, value):
if name in self._validators:
self._validators[name](value)
original_setattr(self, name, value)
namespace['__setattr__'] = validated_setattr
return super().__new__(mcs, name, bases, namespace)
class AutoPropertyMeta(type):
"""自动属性元类"""
def __new__(mcs, name, bases, namespace):
# 为所有以_开头的属性创建property
for key, value in list(namespace.items()):
if key.startswith('_') and not key.startswith('__'):
prop_name = key[1:] # 去掉下划线
if prop_name not in namespace:
namespace[prop_name] = mcs._create_property(key)
return super().__new__(mcs, name, bases, namespace)
@staticmethod
def _create_property(private_name):
def getter(self):
return getattr(self, private_name)
def setter(self, value):
setattr(self, private_name, value)
return property(getter, setter)
def test_utility_metaclasses():
"""测试实用元类"""
print("=== 实用元类测试 ===")
# 测试单例元类
class DatabaseConnection(metaclass=UtilityMetaclasses.SingletonMeta):
def __init__(self):
self.connection_id = id(self)
print(f"创建数据库连接: {self.connection_id}")
print("\n1. 单例模式测试:")
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(f"db1 is db2: {db1 is db2}")
# 测试验证元类
def positive_validator(value):
if value <= 0:
raise ValueError("值必须为正数")
class Product(metaclass=UtilityMetaclasses.ValidatedMeta):
def __init__(self, name, price):
self.name = name
self.price = price
# 为price属性添加验证器
price = property(lambda self: self._price)
price._validator = positive_validator
print("\n2. 属性验证测试:")
try:
product = Product("Laptop", 1000)
print(f"产品创建成功: {product.name}, ${product.price}")
product.price = -100 # 这会触发验证错误
except ValueError as e:
print(f"验证错误: {e}")
# 测试自动属性元类
class Person(metaclass=UtilityMetaclasses.AutoPropertyMeta):
def __init__(self, name, age):
self._name = name
self._age = age
print("\n3. 自动属性测试:")
person = Person("Alice", 25)
print(f"通过属性访问: {person.name}, {person.age}")
person.name = "Bob"
print(f"修改后: {person.name}")
test_utility_metaclasses()
| 单例模式元类 | 属性验证元类 | 自动属性元类 |
| 通过元类的__call__方法控制实例化过程,确保一个类只会创建一个实例。 使用类变量_instances字典缓存已创建的实例。 | 在类创建时收集带有验证器的属性,并重写__setattr__方法,实现属性赋值时自动验证。 实现:遍历类命名空间,寻找带有_validator属性的属性。将验证器函数存入_validators字典。重写__setattr__,在赋值前调用对应的验证器。 | 自动为所有以单下划线开头的私有属性生成对应的property,实现属性的封装与访问控制。 实现:在__new__方法中遍历命名空间,查找以_开头但不以__开头的属性。 为每个私有属性生成对应的getter和setter,绑定为公开属性 |
| 应用场景:需要全局唯一实例的资源管理,如数据库连接、配置管理器等。 测试结果:DatabaseConnection类通过该元类实现单例,db1 is db2返回True,证明实例唯一。 | 应用场景:需要对属性赋值进行严格校验的场景,如数据模型、配置参数等。 测试结果:Product类的price属性绑定了正数验证器,赋值负数时抛出ValueError,保证数据合法。 | 应用场景:需要简化属性封装代码,避免手动写大量property的场景。 测试结果:Person类自动生成name和age属性,支持直接访问和赋值,代码简洁优雅。 |
描述符协议深度应用
描述符是实现了__get__、__set__、__delete__方法的对象,用于管理另一个对象的属性访问。通过描述符,可以自定义属性的读取、赋值和删除行为。
class DescriptorProtocol:
"""完整的描述符协议演示"""
class BasicDescriptor:
"""基础描述符实现"""
def __init__(self, name=None):
self.name = name
self.data = {}
def __set_name__(self, owner, name):
"""Python 3.6+的新特性,自动设置属性名"""
self.name = name
print(f" 描述符 {name} 绑定到类 {owner.__name__}")
def __get__(self, instance, owner):
"""获取属性值"""
if instance is None:
return self
value = self.data.get(id(instance), "未设置")
print(f" 获取 {owner.__name__}.{self.name} = {value}")
return value
def __set__(self, instance, value):
"""设置属性值"""
print(f" 设置 {instance.__class__.__name__}.{self.name} = {value}")
self.data[id(instance)] = value
def __delete__(self, instance):
"""删除属性"""
print(f" 删除 {instance.__class__.__name__}.{self.name}")
self.data.pop(id(instance), None)
class TypedDescriptor:
"""类型检查描述符"""
def __init__(self, expected_type, default=None):
self.expected_type = expected_type
self.default = default
self.data = {}
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return self.data.get(id(instance), self.default)
def __set__(self, instance, value):
if not isinstance(value, self.expected_type):
raise TypeError(
f"{self.name} 必须是 {self.expected_type.__name__} 类型,"
f"得到 {type(value).__name__}"
)
self.data[id(instance)] = value
def __delete__(self, instance):
self.data.pop(id(instance), None)
class ValidatedDescriptor:
"""带验证的描述符"""
def __init__(self, validator=None, default=None):
self.validator = validator
self.default = default
self.data = {}
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return self.data.get(id(instance), self.default)
def __set__(self, instance, value):
if self.validator:
self.validator(value)
self.data[id(instance)] = value
def __delete__(self, instance):
self.data.pop(id(instance), None)
def test_descriptors():
"""测试描述符"""
print("=== 描述符协议测试 ===")
# 定义验证函数
def positive_number(value):
if value <= 0:
raise ValueError("必须是正数")
def valid_email(value):
if '@' not in value:
raise ValueError("无效的邮箱格式")
class User:
# 使用不同类型的描述符
name = DescriptorProtocol.BasicDescriptor()
age = DescriptorProtocol.TypedDescriptor(int, 0)
salary = DescriptorProtocol.ValidatedDescriptor(positive_number, 0)
email = DescriptorProtocol.ValidatedDescriptor(valid_email, "")
def __init__(self, name, age, salary, email):
self.name = name
self.age = age
self.salary = salary
self.email = email
def __str__(self):
return f"User(name={self.name}, age={self.age}, salary={self.salary}, email={self.email})"
print("\n1. 创建用户:")
user = User("li", 25, 50000, "alice@example.com")
print(user)
print("\n2. 修改属性:")
user.name = "li mrs"
user.age = 26
print("\n3. 类型检查测试:")
try:
user.age = "not a number"
except TypeError as e:
print(f"类型错误: {e}")
print("\n4. 验证测试:")
try:
user.salary = -1000
except ValueError as e:
print(f"验证错误: {e}")
try:
user.email = "invalid-email"
except ValueError as e:
print(f"验证错误: {e}")
print("\n5. 删除属性:")
del user.name
print(f"删除后的name: {user.name}")
test_descriptors()
高级属性描述符
import weakref
class AdvancedDescriptors:
"""高级描述符模式"""
class CachedProperty:
"""缓存属性描述符"""
def __init__(self, func):
self.func = func
self.name = func.__name__
self.__doc__ = func.__doc__
def __get__(self, instance, owner):
if instance is None:
return self
# 检查是否已缓存
cache_name = f'_cached_{self.name}'
if hasattr(instance, cache_name):
print(f" 使用缓存值: {self.name}")
return getattr(instance, cache_name)
# 计算并缓存值
print(f" 计算属性: {self.name}")
value = self.func(instance)
setattr(instance, cache_name, value)
return value
def __set__(self, instance, value):
# 允许手动设置缓存值
cache_name = f'_cached_{self.name}'
setattr(instance, cache_name, value)
def __delete__(self, instance):
# 清除缓存
cache_name = f'_cached_{self.name}'
if hasattr(instance, cache_name):
delattr(instance, cache_name)
class ObservableDescriptor:
"""可观察的描述符"""
def __init__(self, default=None):
self.default = default
self.data = weakref.WeakKeyDictionary()
self.observers = weakref.WeakKeyDictionary()
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return self.data.get(instance, self.default)
def __set__(self, instance, value):
old_value = self.data.get(instance, self.default)
self.data[instance] = value
# 通知观察者
if instance in self.observers:
for callback in self.observers[instance]:
callback(instance, self.name, old_value, value)
def add_observer(self, instance, callback):
"""添加观察者"""
if instance not in self.observers:
self.observers[instance] = []
self.observers[instance].append(callback)
def remove_observer(self, instance, callback):
"""移除观察者"""
if instance in self.observers:
if callback in self.observers[instance]:
self.observers[instance].remove(callback)
class LazyDescriptor:
"""延迟加载描述符"""
def __init__(self, loader_func):
self.loader_func = loader_func
self.data = weakref.WeakKeyDictionary()
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
# 检查是否已加载
if instance not in self.data:
print(f" 延迟加载: {self.name}")
self.data[instance] = self.loader_func(instance)
return self.data[instance]
def test_advanced_descriptors():
"""测试高级描述符"""
print("=== 高级描述符测试 ===")
class DataProcessor:
# 缓存属性
@AdvancedDescriptors.CachedProperty
def expensive_calculation(self):
"""昂贵的计算,结果会被缓存"""
import time
print("执行昂贵的计算...")
time.sleep(0.1) # 模拟耗时操作
return sum(range(1000000))
# 可观察属性
status = AdvancedDescriptors.ObservableDescriptor("idle")
# 延迟加载属性
def _load_config(self):
print("从文件加载配置...")
return {"setting1": "value1", "setting2": "value2"}
config = AdvancedDescriptors.LazyDescriptor(_load_config)
def __init__(self, name):
self.name = name
# 为status属性添加观察者 - 通过类访问描述符对象
def status_changed(instance, attr_name, old_value, new_value):
print(f" {instance.name} 的 {attr_name} 从 {old_value} 变为 {new_value}")
# 通过类而不是实例来访问描述符对象
descriptor = type(self).status
descriptor.add_observer(self, status_changed)
print("\n1. 缓存属性测试:")
processor = DataProcessor("Processor1")
# 第一次访问会计算
result1 = processor.expensive_calculation
print(f"第一次结果: {result1}")
# 第二次访问使用缓存
result2 = processor.expensive_calculation
print(f"第二次结果: {result2}")
print("\n2. 可观察属性测试:")
processor.status = "running"
processor.status = "completed"
processor.status = "idle"
print("\n3. 延迟加载测试:")
# 第一次访问会加载
config1 = processor.config
print(f"配置: {config1}")
# 第二次访问使用已加载的数据
config2 = processor.config
print(f"再次访问配置: {config2}")
if __name__ == "__main__":
test_advanced_descriptors()
缓存属性(CachedProperty):通过描述符缓存计算结果,避免重复计算,提升性能。支持手动设置和删除缓存。
可观察属性(ObservableDescriptor):属性值变化时通知注册的观察者,适合实现事件驱动和响应式编程。
延迟加载属性(LazyDescriptor):属性首次访问时才加载数据,节省资源,适合配置加载、懒初始化等场景。
实战
ORM
ORM(Object-Relational Mapping,面向对象关系映射)
Django ORM的魔法
# Django中这样定义模型
class User(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
age = models.IntegerField()
# 但实际上发生了什么?
user = User(name="Alice", email="alice@example.com", age=25)
print(type(user.name)) # <class 'str'> 而不是 CharField
print(User.objects.all()) # 神奇的查询接口从哪来的? 这背后的魔法正是元类和描述符的杰作
现在元类和描述符知识应用到实际项目中,构建一个完整的ORM框架
简化版ORM
import sqlite3
from typing import Any, List, Optional
class SimpleORM:
"""简化版ORM框架"""
class Field:
"""字段基类"""
def __init__(self, sql_type: str, primary_key=False, default=None):
self.sql_type = sql_type
self.primary_key = primary_key
self.default = default
self.name = None
def __set_name__(self, owner, name):
self.name = name
def to_sql(self):
"""生成SQL字段定义"""
parts = [self.name, self.sql_type]
if self.primary_key:
parts.append("PRIMARY KEY")
if self.default is not None:
parts.append(f"DEFAULT {self.default}")
return " ".join(parts)
class IntegerField(Field):
def __init__(self, primary_key=False, default=None):
super().__init__("INTEGER", primary_key, default)
class TextField(Field):
def __init__(self, default=None):
super().__init__("TEXT", False, default)
class Model:
"""模型基类"""
_table_name = None
_fields = {}
def __init__(self, **kwargs):
for field_name in self._fields:
value = kwargs.get(field_name, self._fields[field_name].default)
setattr(self, field_name, value)
def __init_subclass__(cls, **kwargs):
"""自动收集字段信息"""
cls._fields = {}
for attr_name, attr_value in cls.__dict__.items():
if isinstance(attr_value, SimpleORM.Field):
cls._fields[attr_name] = attr_value
attr_value.__set_name__(cls, attr_name)
if cls._table_name is None:
cls._table_name = cls.__name__.lower()
@classmethod
def create_table(cls, conn):
"""创建数据表"""
field_defs = [field.to_sql() for field in cls._fields.values()]
sql = f"CREATE TABLE IF NOT EXISTS {cls._table_name} ({', '.join(field_defs)})"
conn.execute(sql)
conn.commit()
def save(self, conn):
"""保存对象到数据库"""
field_names = list(self._fields.keys())
values = [getattr(self, name) for name in field_names]
placeholders = ', '.join(['?' for _ in field_names])
sql = f"INSERT INTO {self._table_name} ({', '.join(field_names)}) VALUES ({placeholders})"
conn.execute(sql, values)
conn.commit()
@classmethod
def all(cls, conn) -> List['Model']:
"""获取所有记录"""
sql = f"SELECT * FROM {cls._table_name}"
cursor = conn.execute(sql)
results = []
for row in cursor.fetchall():
kwargs = {name: row[i] for i, name in enumerate(cls._fields)}
results.append(cls(**kwargs))
return results
@classmethod
def filter(cls, conn, **kwargs) -> List['Model']:
"""条件查询"""
conditions = [f"{key} = ?" for key in kwargs]
values = list(kwargs.values())
sql = f"SELECT * FROM {cls._table_name} WHERE {' AND '.join(conditions)}"
cursor = conn.execute(sql, values)
results = []
for row in cursor.fetchall():
row_kwargs = {name: row[i] for i, name in enumerate(cls._fields)}
results.append(cls(**row_kwargs))
return results
def __repr__(self):
fields_str = ', '.join([f"{k}={v}" for k, v in self.__dict__.items()])
return f"{self.__class__.__name__}({fields_str})"
# 使用示例
def test_simple_orm():
print("=== 简化版ORM测试 ===")
# 定义模型
class User(SimpleORM.Model):
_table_name = "users"
id = SimpleORM.IntegerField(primary_key=True)
name = SimpleORM.TextField()
email = SimpleORM.TextField()
age = SimpleORM.IntegerField(default=0)
class Post(SimpleORM.Model):
id = SimpleORM.IntegerField(primary_key=True)
title = SimpleORM.TextField()
content = SimpleORM.TextField()
author_id = SimpleORM.IntegerField()
# 创建数据库连接
conn = sqlite3.connect(':memory:')
# 创建表
User.create_table(conn)
Post.create_table(conn)
print(" 数据表创建完成")
# 创建记录
user1 = User(id=1, name="li", email="li@example.com", age=25)
user1.save(conn)
user2 = User(id=2, name="liu", email="liu@example.com", age=30)
user2.save(conn)
post1 = Post(id=1, title="Python教程", content="学习Python编程", author_id=1)
post1.save(conn)
post2 = Post(id=2, title="数据分析", content="数据科学入门", author_id=2)
post2.save(conn)
# 查询所有用户
print("\n所有用户:")
users = User.all(conn)
for user in users:
print(f" {user}")
# 条件查询
print("\n年龄大于25的用户:")
older_users = User.filter(conn, age=30)
for user in older_users:
print(f" {user}")
# 查询文章
print("\n所有文章:")
posts = Post.all(conn)
for post in posts:
print(f" {post}")
conn.close()
print("\n ORM测试完成")
if __name__ == "__main__":
test_simple_orm()
元类的最佳实践
class MetaclassBestPractices:
"""元类使用最佳实践"""
@staticmethod
def when_to_use_metaclasses():
"""何时使用元类"""
print("=== 元类使用场景 ===")
# 场景1: 单例模式
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 DatabaseConnection(metaclass=SingletonMeta):
def __init__(self):
self.connection_id = id(self)
# 场景2: 注册模式
class RegistryMeta(type):
registry = {}
def __new__(mcs, name, bases, namespace):
cls = super().__new__(mcs, name, bases, namespace)
if hasattr(cls, 'register_name'):
mcs.registry[cls.register_name] = cls
return cls
class Handler(metaclass=RegistryMeta):
pass
class UserHandler(Handler):
register_name = 'user'
class OrderHandler(Handler):
register_name = 'order'
print("注册的处理器:", RegistryMeta.registry)
# 场景3: API包装
class APIMeta(type):
def __new__(mcs, name, bases, namespace):
# 为所有方法添加日志
for key, value in namespace.items():
if callable(value) and not key.startswith('_'):
namespace[key] = mcs.add_logging(value)
return super().__new__(mcs, name, bases, namespace)
@staticmethod
def add_logging(func):
def wrapper(*args, **kwargs):
print(f" 调用方法: {func.__name__}")
result = func(*args, **kwargs)
print(f" 方法完成: {func.__name__}")
return result
return wrapper
class APIClient(metaclass=APIMeta):
def get_user(self, user_id):
return f"User {user_id}"
def create_order(self, data):
return f"Order created: {data}"
print("\n测试API客户端:")
client = APIClient()
client.get_user(123)
client.create_order({"item": "laptop"})
@staticmethod
def metaclass_alternatives():
"""元类的替代方案"""
print("\n=== 元类替代方案 ===")
# 替代方案1: 类装饰器
def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class ConfigManager:
def __init__(self):
self.config = {}
# 替代方案2: __init_subclass__
class BaseHandler:
registry = {}
def __init_subclass__(cls, register_name=None, **kwargs):
super().__init_subclass__(**kwargs)
if register_name:
cls.registry[register_name] = cls
class PaymentHandler(BaseHandler, register_name='payment'):
pass
class EmailHandler(BaseHandler, register_name='email'):
pass
print("使用__init_subclass__的注册:", BaseHandler.registry)
# 替代方案3: 描述符
class LoggedMethod:
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
if instance is None:
return self
def wrapper(*args, **kwargs):
print(f" 调用方法: {self.func.__name__}")
result = self.func(instance, *args, **kwargs)
print(f" 方法完成: {self.func.__name__}")
return result
return wrapper
class ServiceClient:
@LoggedMethod
def process_data(self, data):
return f"处理数据: {data}"
print("\n测试描述符方案:")
service = ServiceClient()
service.process_data("test data")
def test_best_practices():
"""测试最佳实践"""
practices = MetaclassBestPractices()
practices.when_to_use_metaclasses()
practices.metaclass_alternatives()
test_best_practices()
描述符设计模式
class DescriptorPatterns:
"""描述符设计模式"""
class ValidationMixin:
"""验证混入类"""
def __init__(self, *validators, **kwargs):
self.validators = validators
super().__init__(**kwargs)
def validate(self, value):
"""执行所有验证器"""
for validator in self.validators:
validator(value)
return value
class TypedAttribute(ValidationMixin):
"""类型化属性"""
def __init__(self, expected_type, *validators, default=None):
self.expected_type = expected_type
self.default = default
self.data = {}
super().__init__(*validators)
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return self.data.get(id(instance), self.default)
def __set__(self, instance, value):
# 类型检查
if value is not None and not isinstance(value, self.expected_type):
raise TypeError(f"{self.name} 必须是 {self.expected_type.__name__} 类型")
# 执行验证
if value is not None:
value = self.validate(value)
self.data[id(instance)] = value
class ComputedAttribute:
"""计算属性"""
def __init__(self, func, *dependencies):
self.func = func
self.dependencies = dependencies
self.cache = {}
self.cache_valid = {}
def __set_name__(self, owner, name):
self.name = name
# 监听依赖属性的变化
for dep in self.dependencies:
self._setup_dependency_monitoring(owner, dep)
def _setup_dependency_monitoring(self, owner, dep_name):
"""设置依赖监听"""
# 这里简化实现,不在元类层面设置监听, 在实际使用中会在实例层面处理
pass
def __get__(self, instance, owner):
if instance is None:
return self
instance_id = id(instance)
# 检查缓存是否有效
if instance_id in self.cache and self.cache_valid.get(instance_id, False):
return self.cache[instance_id]
# 重新计算
value = self.func(instance)
self.cache[instance_id] = value
self.cache_valid[instance_id] = True
return value
def invalidate_cache(self, instance):
"""使缓存失效"""
instance_id = id(instance)
if instance_id in self.cache:
self.cache_valid[instance_id] = False
class ObservableAttribute:
"""可观察属性"""
def __init__(self, default=None):
self.default = default
self.data = {}
self.observers = {}
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return self.data.get(id(instance), self.default)
def __set__(self, instance, value):
old_value = self.data.get(id(instance), self.default)
self.data[id(instance)] = value
# 通知观察者
self._notify_observers(instance, old_value, value)
def observe(self, instance, callback):
"""添加观察者"""
instance_id = id(instance)
if instance_id not in self.observers:
self.observers[instance_id] = []
self.observers[instance_id].append(callback)
def _notify_observers(self, instance, old_value, new_value):
"""通知观察者"""
instance_id = id(instance)
if instance_id in self.observers:
for callback in self.observers[instance_id]:
callback(instance, self.name, old_value, new_value)
def test_descriptor_patterns():
print("=== 描述符设计模式测试 ===")
# 定义验证器
def positive(value):
if value <= 0:
raise ValueError("值必须为正数")
def max_length(length):
def validator(value):
if len(str(value)) > length:
raise ValueError(f"长度不能超过 {length}")
return validator
# 使用描述符模式的类
class Product:
name = DescriptorPatterns.TypedAttribute(str, max_length(50), default="")
price = DescriptorPatterns.TypedAttribute(float, positive, default=0.0)
quantity = DescriptorPatterns.TypedAttribute(int, positive, default=0)
# 计算属性
def _calculate_total(self):
return self.price * self.quantity
total = DescriptorPatterns.ComputedAttribute(_calculate_total, 'price', 'quantity')
# 可观察属性
status = DescriptorPatterns.ObservableAttribute("available")
def __init__(self, name="", price=0.0, quantity=0):
self.name = name
self.price = price
self.quantity = quantity
# 添加状态观察者
def status_changed(instance, attr_name, old_value, new_value):
print(f" 产品状态变化: {old_value} -> {new_value}")
type(self).status.observe(self, status_changed)
def __setattr__(self, name, value):
# 手动处理计算属性缓存失效
if name in ['price', 'quantity'] and hasattr(type(self), 'total'):
type(self).total.invalidate_cache(self)
super().__setattr__(name, value)
print("\n1. 创建产品:")
product = Product("笔记本电脑", 5000.0, 2)
print(f"产品: {product.name}, 价格: {product.price}, 数量: {product.quantity}")
print(f"总价: {product.total}")
print("\n2. 修改属性:")
product.price = 4500.0
print(f"修改价格后总价: {product.total}")
product.quantity = 3
print(f"修改数量后总价: {product.total}")
print("\n3. 状态变化:")
product.status = "out_of_stock"
product.status = "available"
print("\n4. 验证测试:")
try:
product.price = -100.0 # 负数价格
except ValueError as e:
print(f"验证错误: {e}")
try:
product.name = "A" * 100 # 名称过长
except ValueError as e:
print(f"验证错误: {e}")
if __name__ == "__main__":
test_descriptor_patterns()
1087

被折叠的 条评论
为什么被折叠?



