"元类是类的类,是创建类的工厂。掌握元类,就等于掌握了Python面向对象编程的终极武器。"
Python元类编程被誉为Python面向对象编程的"黑魔法"。它允许开发者在类创建时介入并修改类的行为,为框架开发、API设计和代码生成提供了强大的工具。本文将深入探讨Python元类的核心原理,并通过丰富的实战案例展示其在现代开发中的应用。
02|元类基础:理解类的创建机制
类也是对象
在Python中,一切皆对象,类也不例外。当我们定义一个类时,Python实际上创建了一个对象(类对象):
class MyClass:
pass
# 类也是对象
print(type(MyClass)) # <class 'type'>
print(MyClass.__class__) # <class 'type'>
# 可以像操作普通对象一样操作类
MyClass.new_attr = "动态添加的属性"
print(MyClass.new_attr) # 动态添加的属性type():内置元类
type()是Python的内置元类,它有两个作用:
- 当传入一个参数时,返回对象的类型
- 当传入三个参数时,动态创建一个新类
# 使用type()动态创建类
MyDynamicClass = type('MyDynamicClass', (object,), {'x': 5})
# 等价于:
# class MyDynamicClass(object):
# x = 5
obj = MyDynamicClass()
print(obj.x) # 5
print(type(obj)) # <class '__main__.MyDynamicClass'>元类的定义方式
创建自定义元类有两种方式:
方式一:继承type
class MyMeta(type):
def __new__(mcs, name, bases, namespace, **kwargs):
print(f"创建类 {name}")
return super().__new__(mcs, name, bases, namespace)
class MyClass(metaclass=MyMeta):
pass
# 输出:创建类 MyClass方式二:使用__metaclass__属性(Python 2风格,不推荐)
class MyClass:
__metaclass__ = MyMeta # Python 2语法03|元类实战:自定义类创建过程
控制类属性
元类可以在类创建时检查和修改类的属性:
class AttributeMeta(type):
def __new__(mcs, name, bases, namespace):
# 将所有属性名转换为大写
new_namespace = {}
for attr_name, attr_value in namespace.items():
if not attr_name.startswith('_'):
new_namespace[attr_name.upper()] = attr_value
else:
new_namespace[attr_name] = attr_value
return super().__new__(mcs, name, bases, new_namespace)
class Config(metaclass=AttributeMeta):
debug = False
port = 8080
host = "localhost"
print(Config.DEBUG) # False
print(Config.PORT) # 8080
print(Config.HOST) # localhost
# print(Config.debug) # AttributeError自动注册子类
在框架开发中,经常需要自动注册所有子类:
class PluginMeta(type):
plugins = {}
def __new__(mcs, name, bases, namespace):
cls = super().__new__(mcs, name, bases, namespace)
if name != 'BasePlugin': # 排除基类
PluginMeta.plugins[name] = cls
return cls
class BasePlugin(metaclass=PluginMeta):
def execute(self):
raise NotImplementedError
class DataPlugin(BasePlugin):
def execute(self):
return "处理数据"
class LogPlugin(BasePlugin):
def execute(self):
return "记录日志"
print(PluginMeta.plugins)
# {'DataPlugin': <class '__main__.DataPlugin'>,
# 'LogPlugin': <class '__main__.LogPlugin'>}
# 动态加载所有插件
for name, plugin_cls in PluginMeta.plugins.items():
plugin = plugin_cls()
print(f"{name}: {plugin.execute()}")单例模式实现
使用元类实现线程安全的单例模式:
import threading
class SingletonMeta(type):
_instances = {}
_lock = threading.Lock()
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
with cls._lock:
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class Database(metaclass=SingletonMeta):
def __init__(self):
print("初始化数据库连接")
self.connection = "db_connection"
# 测试单例
import threading
def test_singleton():
db = Database()
print(f"线程 {threading.current_thread().name}: {id(db)}")
threads = [threading.Thread(target=test_singleton) for _ in range(3)]
for t in threads:
t.start()
for t in threads:
t.join()
## 04|元类在框架开发中的实战应用
### ORM框架中的元类
元类在ORM(对象关系映射)框架中发挥着重要作用。下面是一个简化版的ORM实现:
```python
class Field:
def __init__(self, name, column_type):
self.name = name
self.column_type = column_type
def __str__(self):
return f"<{self.name}:{self.column_type}>"
class ModelMeta(type):
def __new__(mcs, name, bases, namespace):
if name == 'Model':
return super().__new__(mcs, name, bases, namespace)
# 获取所有Field属性
fields = {}
for key, value in list(namespace.items()):
if isinstance(value, Field):
fields[key] = value
namespace.pop(key)
namespace['__fields__'] = fields
namespace['__table__'] = name.lower()
return super().__new__(mcs, name, bases, namespace)
class Model(metaclass=ModelMeta):
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
def save(self):
fields = []
params = []
args = []
for key, field in self.__fields__.items():
fields.append(field.name)
params.append('?')
args.append(getattr(self, key, None))
sql = f"INSERT INTO {self.__table__} ({', '.join(fields)}) VALUES ({', '.join(params)})"
print(f"执行SQL: {sql}")
print(f"参数: {args}")
# 定义数据模型
class User(Model):
id = Field('id', 'int')
name = Field('name', 'varchar(50)')
email = Field('email', 'varchar(100)')
class Product(Model):
id = Field('id', 'int')
name = Field('name', 'varchar(100)')
price = Field('price', 'float')
# 使用模型
user = User(id=1, name="张三", email="zhangsan@example.com")
user.save()
# 输出:
# 执行SQL: INSERT INTO user (id, name, email) VALUES (?, ?, ?)
# 参数: [1, '张三', 'zhangsan@example.com']
product = Product(id=1, name="笔记本电脑", price=5999.99)
product.save()
# 输出:
# 执行SQL: INSERT INTO product (id, name, price) VALUES (?, ?, ?)
# 参数: [1, '笔记本电脑', 5999.99]