【Python】元类及元类如何定义
元类的定义及初始化类的流程
类默认由type创建。
怎么让一个类的创建改成其他的东西?用元类。
默认创建类
# 默认创建类,一般写法
class Foo(object):
pass
# type 创建类
type('Foo', (object, ), {'v1': 123, 'func': lambda self: 666})
自定义元类
class Mytype(type):
def __new__(cls, *args, **kwargs):
# 创建类
fooCls = super().__new__(cls, *args, **kwargs)
return fooCls
def __init__(self, *args, **kwargs):
super().__init__(self, *args, **kwargs)
def __call__(self, *args, **kwargs):
# 1. 调用自己那个类的__new__方法去创建对象
emptyObject = self.__new__(self)
# 2. 调用自己那个类的__init__方法去初始化
self.__init__(emptyObject, *args, **kwargs)
return emptyObject
class Foo(object, metaclass=MyType):
def __init__(self, name, *args, **kwargs):
self.name = name
v1 = Foo('alex')
# 自定义type 创建类
class Foo(Object, metaclass=MyType):
pass
# Foo是个对象,由MyType创建,所以会执行MyType里的__new__和__init__方法。
类加()执行的是__new__和__init__方法
对象加()执行的是__call__方法
class Foo(object):
def __call__(self, *args, **kwargs):
return 1
obj = Foo()
obj()
在__call__方法里面会初始化Foo对象。
- 比如Foo的__init__中有一些赋值或者逻辑,此时在元类的中的__call__会调用类的__init__方法,将Foo.__init__接收到的参数传入到type的__init__方法中,在type.__init__中完成赋值或逻辑操作。
不管是自定义的元类还是使用默认的类的实例方法(默认就是用type),类的初始化都是在元类的__call__方法中实现的。
- 创建类的时候是调用了元类的__new__和__init__方法,此时这里不执行__call__方法。
- 实例化这个类的时候才调用了元类的__call__方法,这时候才会调用元类中的__call__方法,在这个元类中的__call__方法里会初始化类对象(调用类对象的__new__和__init__方法)
- 如果想调用自己类中的__call__方法,就在自己实例化类的对象后面加括号。
所有创建的类都是元类的对象
# 关系图
# 元类
class Mytype(): pass
# 自己创建的类,这里会调用元类的__new__和__init__方法。
class Foo(): pass
# 自己创建的类的实例化(对象),这里会调用元类的__call__方法。
v1 = Foo()
# 调用自己类的__call__方法。
v1()
元类深入
- 类中metaclass,自己类由metaclass定义的类来创建。
- 类继承某个类,父类有自定义metaclass,自己类由metaclass定义的类来创建。
class FormMeta(type): pass
def withMetaclass(meta, base=object):
# Foo = type('Foo', (object, ), {'v1': 123, 'func': lambda self: 666})
# 返回一个类(基于meta创建了一个类),这个对象的元类是meta参数,并且继承base参数,类名是NewBase
return meta('NewBase', (base, ), {})
class NewBase(BaseForm, metaclass=FormMeta): pass
class Form(withMetaclass(FormMeta, BaseFrom)): pass
# 等价于
class Form(NewBase): pass
元类总结
元类的作用
- 在类创建,实例化对象前后,可以自定义一些功能。