Python元类相关技术问询:类定义中metaclass关键字参数原理及type()创建类时的传参方法
嘿,很高兴你在深挖元类这个Python里有点“魔法”的特性!让我逐个帮你理清这两个疑问:
问题1:类定义中metaclass=...关键字参数的原理
当你用class关键字定义一个类时,Python背后其实是在调用元类来创建这个类对象——默认情况下,所有类的元类都是type,也就是说,你定义的MyClass本质上是type的一个实例。
而metaclass=Metaclass这个参数,就是明确告诉Python:“别用默认的type来生成这个类了,改用我指定的Metaclass来创建它”。这里要注意,Metaclass必须是type的子类(毕竟元类本身就是用来创建类的“类”)。
当你写下class MyClass(metaclass=Metaclass):时,Python会走这么一套流程:
- 首先调用
Metaclass.__prepare__方法(如果元类里定义了的话),生成一个用来存放类属性的命名空间字典; - 接着执行类体里的所有代码,把定义的方法、属性都塞进这个命名空间;
- 然后调用
Metaclass.__new__方法,传入类名、基类元组、命名空间这三个参数,最终创建出MyClass这个类对象; - 最后(可选)调用
Metaclass.__init__方法,对刚创建好的类对象做一些初始化操作。
这个metaclass参数是Python 3专门为类定义新增的语法,Python 2里是用类内部的__metaclass__属性来指定的,两者作用一致但写法不同。你之前没见过这种形式,是因为它是类定义语法特有的关键字参数,和函数的关键字参数不是一回事,但设计上借鉴了关键字参数的直观性,让你能清晰指定元类。
问题2:用type()创建类时如何指定元类
答案其实很直白:不用type(),直接调用你的自定义元类就行。
因为type()本身就是默认的元类,当你写type(class_name, bases, attrs)时,本质上是在调用type这个元类的构造方法来生成类对象。那如果要使用自定义元类,只需要把type换成你的元类,参数格式完全一样:
举个例子,先定义自定义元类:
class Metaclass(type): def __new__(cls, name, bases, attrs): # 加个自定义属性 attrs['created_by_metaclass'] = True return super().__new__(cls, name, bases, attrs)
然后用这个元类创建类:
# 用自定义元类代替type()来创建类 MyDynamicClass = Metaclass( 'MyDynamicClass', (object,), # 基类元组 {'greet': lambda self: print('Hello from dynamic class!')} )
这样创建出来的MyDynamicClass,它的元类就是Metaclass,和你用class MyDynamicClass(metaclass=Metaclass):定义的效果完全一致。
简单总结:type()是默认元类的调用方式,自定义元类继承自type,所以调用自定义元类的参数和type()完全相同——类名、基类元组、属性字典。
内容的提问来源于stack exchange,提问作者WW00WW

