python中元类在创建类和实例的作用
最近在研究backtrader
的底层源代码,作者用类若干的类和元类,以前没有接触过元类,现在经过查了一些资料,知道了元类是创建类的类,可以用来控制类的创建和实例的创建过程,也可以隐性地继承属性和方法,元类的常见的应用有创建单类模式、ORM。
由于元类的理解比较抽象,可以用下面的代码理解元类在创建类和实例时的作用,
- metaClass1: 继承自
type
类的元类 - metaClass2: 继承自
metaClass1
的元类 - A: 由
metaClass1
创建的类 - M:继承自
A
的子类 - a: 类
A
的实例化对象 - m: 类
M
的实例化对象
class metaClass1(type):
def __new__(cls, clsname, bases, dct):
print("基于type的类metaClass1,....__new__")
return type.__new__(cls, clsname, bases, dct)
def __call__(self, *args, **kwargs):
print("基于type的类metaClass1,....__call__")
return super().__call__(*args, **kwargs)
class metaClass2(metaClass1):
def __new__(cls, clsname, bases, dct):
print("基于metaClass1的类metaClass2,....__new__")
return super().__new__(cls, clsname, bases, dct)
def __call__(self, *args, **kwargs):
print("基于metaClass1的类metaClass2,....__call__")
return super().__call__(*args, **kwargs)
print("创建类A-------")
class A(metaclass=metaClass2):
def __new__(cls, *agrs, **kwds):
inst = super().__new__(cls, *agrs, **kwds)
print("由metaClass2创建的类A,....__new__...正在创建类的实例")
return inst
def __init__(self):
print("由metaClass2创建的类A,....__init__...正在创建类的实例")
super().__init__()
class metaClass3(type):
def __new__(cls, clsname, bases, dct):
print("基于metaClass1的类metaClass2,....__call__")
return super().__new__(cls, clsname, bases, dct)
print('创建A的子类M-------')
class M(A, metaclass=type):
def __new__(cls, *agrs, **kwds):
print("类A的子类M,...__new__...正在创建类的实例")
return super().__new__(cls, *agrs, **kwds)
def __init__(self):
print("类A的子类M,...__init__...正在创建类的实例")
super().__init__()
print("创建A的实例--------")
a = A()
print("创建M的实例--------")
m = M()
输出
创建类A-------
基于metaClass1的类metaClass2,....__new__
基于type的类metaClass1,....__new__
创建A的子类M-------
基于metaClass1的类metaClass2,....__new__
基于type的类metaClass1,....__new__
创建A的实例--------
基于metaClass1的类metaClass2,....__call__
基于type的类metaClass1,....__call__
由metaClass2创建的类A,....__new__...正在创建类的实例
由metaClass2创建的类A,....__init__...正在创建类的实例
创建M的实例--------
基于metaClass1的类metaClass2,....__call__
基于type的类metaClass1,....__call__
类A的子类M,...__new__...正在创建类的实例
由metaClass2创建的类A,....__new__...正在创建类的实例
类A的子类M,...__init__...正在创建类的实例
由metaClass2创建的类A,....__init__...正在创建类的实例
分析
这里由两条关系:父类-子类继承关系、元类-类创建关系。
创建类
通过元类创建类时,子类M
不必另外声明元类,因为创建M
时,会默认调用父类A
的元类,如果设置metaclass
为父类的元类外的别的元类,程序会出错。用元类创建类时,依次调用元类的__new__
方法,该方法的参数分别为:
cls
:类对象,类似class
中的self
clsname
: 类名,就像例子中的“A”、“M”bases
:类的父类dct
:类的属性,是一个字典
通过这些参数可以看出,这是在得到类的属性后才会进入到元类中。
创建实例
创建实例涉及到类的__init__
、__new__
和元类的__call__
。
__call__
:首先调用父类的该方法,如果元类有继承关系,先依次(子元类->父元类)调用完所有元类的__call__
方法,接着调用类的__new__
方法__new__
:调用完元类的__new__
方法后,接着调用类的__new__
,如果类有继承关系,则依次(子类->父类)调用完所有类的__new__
方法__init__
:调用完所有类的__new__
方法后,接着调用类的__init__
,如果有类的继承关系,则依次(子类->父类)调用所有类的__init__
方法