[python]元类
最近工作中,一直可以看到元类的代码,之前使用的较少,现做笔记来彻底搞清元类的概念
1 什么是元类
在 Python 中,元类(Metaclass)是一个高级且复杂的概念,它涉及到 Python 的对象模型和类的创建机制。
换句话说,元类控制类的创建,跟类与实例的关系类似。
类和实例的关系:类是实例的模板,通过类可以创建实例。
元类和类的关系:元类是类的模板,通过元类可以创建类。
2 默认的元类
type 是一个内置的元类,它负责创建所有的类。例如:
class MyClass:
pass
print(type(MyClass)) # 输出:<class 'type'>
3 如何定义元类
元类本质上是一个类,但它必须继承自 type。以下是一个简单的元类示例:
class MyMeta(type):
def __new__(cls, name, bases, dct):
# 在类被创建之前,可以修改类的属性和方法
dct['new_attribute'] = 'This is a new attribute'
return super().__new__(cls, name, bases, dct)
class MyClass(metaclass=MyMeta):
pass
print(hasattr(MyClass, 'new_attribute')) # 输出:True
print(MyClass.new_attribute) # 输出:This is a new attribute
4 元类的关键方法
__new__ 方法:在类被创建之前调用,用于创建类对象。它接收以下参数:
cls:元类本身。
name:类的名称。
bases:类的基类元组。
dct:包含类的属性和方法的字典。
__init__ 方法:在类被创建之后调用,用于初始化类对象。它接收与 __new__ 相同的参数。
__call__ 方法:当类被实例化时调用,用于控制类的实例化过程
5 元类的使用场景
5.1 自动添加属性或方法
class AutoAddMeta(type):
def __new__(cls, name, bases, dct):
dct['auto_added_method'] = lambda self: "This is an auto-added method"
return super().__new__(cls, name, bases, dct)
class MyClass(metaclass=AutoAddMeta):
pass
obj = MyClass()
print(obj.auto_added_method()) # 输出:This is an auto-added method
5.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 SingletonClass(metaclass=SingletonMeta):
pass
obj1 = SingletonClass()
obj2 = SingletonClass()
print(obj1 is obj2) # 输出:True
5.3 检查类的实现
class InterfaceMeta(type):
def __new__(cls, name, bases, dct):
if 'required_method' not in dct:
raise TypeError(f"Class {name} must implement 'required_method'")
return super().__new__(cls, name, bases, dct)
class MyClass(metaclass=InterfaceMeta):
def required_method(self):
return "Implemented method"
# 下面的代码会报错,因为没有实现 required_method
# class MyIncompleteClass(metaclass=InterfaceMeta):
# pass
5.4 动态修改类的继承关系
假设我们有两个基类 BaseClass1 和 BaseClass2,我们希望在类创建时动态地选择其中一个作为父类。
class BaseClass1:
def method(self):
return "Method from BaseClass1"
class BaseClass2:
def method(self):
return "Method from BaseClass2"
class DynamicMeta(type):
def __new__(cls, name, bases, dct):
# 动态修改 bases 参数
if name == "MyClass1":
bases = (BaseClass1,) # 将 BaseClass1 设置为父类
elif name == "MyClass2":
bases = (BaseClass2,) # 将 BaseClass2 设置为父类
return super().__new__(cls, name, bases, dct)
# 使用 DynamicMeta 作为元类
class MyClass1(metaclass=DynamicMeta):
pass
class MyClass2(metaclass=DynamicMeta):
pass
# 测试
obj1 = MyClass1()
print(obj1.method()) # 输出:Method from BaseClass1
obj2 = MyClass2()
print(obj2.method()) # 输出:Method from BaseClass2

浙公网安备 33010602011771号