Python 元类基础

什么是元类

在Python中“万物”皆是对象,当然也是对象。

通过类我们可以创建实例对象:

class A:
pass

a = A()

那么通过什么我们创建类呢?答案是元类

即:类是元类的实例

class A:
pass

print(isinstance(A, type)) # True
print(issubclass(A, object)) # True

元类的作用

元类可以定制化类的创建过程。例如修改类的属性、方法,添加新的属性、方法,甚至可以拦截类的创建过程。

使用type创建类

type既可以判断对象的类型

type(123) # <class 'int'>

也是所有类的顶层元类

print(type(int))    # <class 'type'>
print(type(str)) # <class 'type'>
print(type(object)) # <class 'type'>
print(type(type)) # <class 'type'> (type 也是它自己的实例)

也可以通过type(name, bases, attrs)动态创建类,

其中,

  • name:类的名字;
  • bases:类继承的父类集合
  • attrs:类的属性、方法字典
class Person1:
def __init__(self, name):
self.name = name

def init(self, name):
self.name = name


Person2 = type('Person', (), {'__init__': init})

在这个例子中,Person2和Person1的效果一模一样,因为Python解释器在读到class Person1的定义时就是调用的type。因此通过Person2创建实例:

p = Person2('John')
p.name # John

自定义元类

所有类默认情况下,元类是type,当然也可以指定类的元类(当然了,所有类的元类最终都指向了type)

class AMetaClass(type):
#继承了type的既是元类
#元类命名最好是MetaClass后缀
pass

class A(metaclass = AMetaClass):
pass

这个例子中A的元类是AMetaClass。

我们知道,创建一个实例对象,会调用类的__new__方法。同样的,创建一个类,会调用其元类的__new__方法。因此在元类中重写__new__方法即可拦截类的生成方式。

class AMetaClass(type):
def __new__(cls, name, bases, attrs):
return super().__new__(cls, name, bases, attrs)

class A(metaclass = AMetaClass):
pass

那么这样做的意义是什么?

通常来讲,对于普通开发者,并不需要元类编程。但凡事总有例外。

元类编程的最大作用之一,是可以开发框架。

使用元类创建简单的ORM框架

这里使用元类创建简单的ORM框架作为案例。

我希望对于自定义继承自BaseModel的类,其包含一个类变量table_name,变量名为小写的类名。

class User(BaseModel):
pass

print(User.table_name) # user

这里就要用到元类,我们要拦截BaseModel类的生成,在生成其子类的时候给它添加属性table_name,因此完整的代码是:

class ModelMetaClass(type):
def __new__(cls, name, bases, attrs):
if name != 'BaseModel':
attrs['table_name'] = name.lower()
return super().__new__(cls, name, bases, attrs)

class BaseModel(metaclass=ModelMetaClass):
pass

class User(BaseModel):
pass

print(User.table_name) # 输出:user
文章作者: Met Guo
文章链接: https://guoyujian.github.io/2025/03/26/Python-%E5%85%83%E7%B1%BB%E5%9F%BA%E7%A1%80/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Gmet's Blog