python元类
大约 4 分钟
1. 什么是元类
在python中,一切皆对象,包括类本身。元类是创建类对象的类。就像类是用来创建实例的模板一样,元类是创建类的模板。
class MyClass:
pass
obj = MyClass()
print(f"实例的类型: {type(obj)}") # <class '__main__.MyClass'>
print(f"类的类型: {type(MyClass)}") # <class 'type'>
print(f"type的类型: {type(type)}") # <class 'type'>
# 所以:
# 实例 obj 是 MyClass 类的对象
# 类 MyClass 是 type 类的对象
# 元类 type 是 type 类的对象(type是自身的实例)
因此,python的类也可以直接由type创建
# 传统方式创建类
class Person:
name = "Unknown"
def say_hello(self):
return f"Hello, I'm {self.name}"
# 等价于使用type动态创建
Person = type(
'Person',
(),
{
'name': 'Unknown',
'say_hello': lambda self: f"Hello, I'm {self.name}"
}
)
# 两种方式创建的对象完全一样
p1 = Person()
print(p1.say_hello()) # Hello, I'm Unknown
2. 自定义元类
要自定义元类,需要继承type并重写__new__和__init__
class MyMeta(type):
"""自定义元类"""
def __new__(cls, name, bases, attrs):
print(f"🐍 元类 __new__ 被调用!")
print(f" 创建类: {name}")
print(f" 基类: {bases}")
print(f" 属性: {list(attrs.keys())}")
# 可以修改属性
if 'version' not in attrs:
attrs['version'] = '1.0.0'
# 自动添加类文档
if '__doc__' not in attrs or not attrs['__doc__']:
attrs['__doc__'] = f"这是自动生成的 {name} 类"
# 调用父类的__new__来实际创建类
return super().__new__(cls, name, bases, attrs)
def __init__(self, name, bases, attrs):
print(f"🐍 元类 __init__ 被调用!")
super().__init__(name, bases, attrs)
# 使用自定义元类创建类
class MyClass(metaclass=MyMeta):
author = "Anonymous"
def method(self):
return "Hello"
print("=== 创建实例 ===")
obj = MyClass()
print(f"类版本: {MyClass.version}")
print(f"作者: {MyClass.author}")
print(f"文档: {MyClass.__doc__}")
🐍 元类 __new__ 被调用!
创建类: MyClass
基类: ()
属性: ['__module__', '__qualname__', 'author', 'method']
🐍 元类 __init__ 被调用!
=== 创建实例 ===
类版本: 1.0.0
作者: Anonymous
文档: 这是自动生成的 MyClass 类
3. 元类的应用
自动注册子类
class PluginMeta(type):
"""插件系统的元类 - 自动注册所有插件"""
def __init__(cls, name, bases, attrs):
super().__init__(name, bases, attrs)
# 跳过基类
if name == 'BasePlugin':
return
# 初始化注册表
if not hasattr(cls, 'registry'):
cls.registry = {}
# 自动注册插件
plugin_name = attrs.get('plugin_name', name.lower())
cls.registry[plugin_name] = cls
print(f"✅ 注册插件: {plugin_name}")
class BasePlugin(metaclass=PluginMeta):
"""插件基类"""
pass
# 自动注册这些插件类
class EmailPlugin(BasePlugin):
plugin_name = "email"
class SMSPlugin(BasePlugin):
plugin_name = "sms"
class PushPlugin(BasePlugin):
pass # 使用类名小写作为名称
print("\n已注册的插件:")
for name, plugin_class in BasePlugin.registry.items():
print(f" {name}: {plugin_class}")
ORM框架
class PluginMeta(type):
"""插件系统的元类 - 自动注册所有插件"""
def __init__(cls, name, bases, attrs):
super().__init__(name, bases, attrs)
# 跳过基类
if name == 'BasePlugin':
return
# 初始化注册表
if not hasattr(cls, 'registry'):
cls.registry = {}
# 自动注册插件
plugin_name = attrs.get('plugin_name', name.lower())
cls.registry[plugin_name] = cls
print(f"✅ 注册插件: {plugin_name}")
class BasePlugin(metaclass=PluginMeta):
"""插件基类"""
pass
# 自动注册这些插件类
class EmailPlugin(BasePlugin):
plugin_name = "email"
class SMSPlugin(BasePlugin):
plugin_name = "sms"
class PushPlugin(BasePlugin):
pass # 使用类名小写作为名称
print("\n已注册的插件:")
for name, plugin_class in BasePlugin.registry.items():
print(f" {name}: {plugin_class}")
@ API验证
class APIMeta(type):
"""API接口验证元类"""
def __new__(cls, name, bases, attrs):
# 收集所有方法
methods = {}
for attr_name, attr_value in attrs.items():
if callable(attr_value) and not attr_name.startswith('_'):
methods[attr_name] = attr_value
# 验证方法是否有文档字符串
for method_name, method in methods.items():
if not method.__doc__:
print(f"⚠️ 警告: 方法 {name}.{method_name} 缺少文档字符串")
# 自动添加API版本信息
attrs['api_version'] = 'v1.0'
return super().__new__(cls, name, bases, attrs)
class UserAPI(metaclass=APIMeta):
"""用户API接口"""
def get_user(self, user_id):
"""根据ID获取用户信息"""
return f"获取用户 {user_id}"
def create_user(self, user_data):
# 这个方法缺少文档字符串
return "创建用户"
# 使用
api = UserAPI()
print(f"API版本: {api.api_version}")
4. 类的创建顺序
__new__: 创建类对象__init__: 初始化类对象__call__: 创建实例
class MyMeta(type):
"""自定义元类"""
def __new__(cls, name, bases, attrs):
print(f"🐍 元类 __new__ 被调用!")
print(f" 创建类: {name}")
print(f" 基类: {bases}")
print(f" 属性: {list(attrs.keys())}")
# 可以修改属性
if 'version' not in attrs:
attrs['version'] = '1.0.0'
# 自动添加类文档
if '__doc__' not in attrs or not attrs['__doc__']:
attrs['__doc__'] = f"这是自动生成的 {name} 类"
# 调用父类的__new__来实际创建类
return super().__new__(cls, name, bases, attrs)
def __init__(self, name, bases, attrs):
print(f"🐍 元类 __init__ 被调用!")
super().__init__(name, bases, attrs)
# 使用自定义元类创建类
class MyClass(metaclass=MyMeta):
author = "Anonymous"
def method(self):
return "Hello"
print("=== 创建实例 ===")
obj = MyClass()
print(f"类版本: {MyClass.version}")
print(f"作者: {MyClass.author}")
print(f"文档: {MyClass.__doc__}")
🐍 元类 __new__ 被调用!
创建类: MyClass
基类: ()
属性: ['__module__', '__qualname__', 'author', 'method']
🐍 元类 __init__ 被调用!
=== 创建实例 ===
类版本: 1.0.0
作者: Anonymous
文档: 这是自动生成的 MyClass 类