1 python通过函数和常规类编写元类
python可以通过函数和常规类编写元类。函数和常规类之间通过type()创建类对象。
1.1 使用简单的工厂函数
python工厂函数定义了一个外部函数,它生成并返回一个嵌套函数,所以调用工厂函数就可以得到嵌套函数的引用。参考《python嵌套函数作用域》
任何可调用对象都可以作为一个元类,比如函数,只要接收传递的参数,并且返回与目标类兼容的对象。因为可调用对象都有__call__()方法。class语句也是调用type()方法,触发__call()方法。
用法
# 定义元类
def metafunc(classname,supers,classdict):
pass
return type(classname,supers,classdict)
# 使用元类
class ClassB(ClassA,metaclass=metafunc)
描述
定义一个工厂函数,接收三个入参,送入到type()内置函数,并且返回type()生成的可调用对象-类对象。
手动调用type()内置函数创建类对象。参考《python元类模型和class语句协议》
classname:字符串,类名;
supers:元组,存放基类;
classdict:类属性字典;
返回:创建名字为classname的类对象,类型为type类。
根据class语句协议,class语句末尾自动调用metaclass,即type()。
示例文章来源地址https://www.toymoban.com/news/detail-807226.html
>>> def metafunc(classname,supers,classdict):
print('工厂函数 metafunc.type:',
'classname: %s' % classname,
'supers: %s' % supers,
'classdict: %s' % classdict,sep='\n')
return type(classname,supers,classdict)
>>> class ClassA:pass
>>> class ClassB(ClassA,metaclass=metafunc):
name='梯阅线条'
def meth(self,arg):
pass
工厂函数 metafunc.type:
classname: ClassB
supers: <class '__main__.ClassA'>
classdict: {'__module__': '__main__', '__qualname__': 'ClassB', 'name': '梯阅线条', 'meth': <function ClassB.meth at 0x0000022F388C88B0>}
>>> cb=ClassB()
>>> cb.name
'梯阅线条'
>>> type(metafunc)
<class 'function'>
>>> type(ClassB)
<class 'type'>
>>> type(cb)
<class '__main__.ClassB'>
1.2 用元类重载类创建调用
用法
# 定义
class SuperMeta(type):
def __call__(meta,classname,supers,classdict):
pass
return type.__call__(meta,classname,supers,classdict)
class SubMeta(type,metaclass=SuperMeta):
def __new__(meta,classname,supers,classdict):
pass
return type.__new__(meta,classname,supers,classdict)
def __init__(Class,classname,supers,classdict):
pass
# 使用
class ClassB(ClassA,metaclass=SubMeta):pass
描述
通过元类的元类重载type的__call__()方法,再显式调用type的__call__()方法,再触发type子类的__new__()和__init__()方法。
(1) 定义元类SubMeta,继承type,并且指定元类metaclass=SuperMeta;
(2) 定义元类的元类SuperMeta,继承type,重载__call__()方法;
(3) 客户类ClassB通过metaclass=SubMeta指定元类;
(4) 通过class协议触发元类SubMeta,再触发元类的元类SuperMeta的__call__()方法;
(5) SuperMeta的__call__()方法显式调用type.__call__();
(6) type.__call__()调用子类SubMeta的__new__()和__init__()方法;
(7) 子类SubMeta的__new__()方法,显式调用type的__new__()创建类对象,赋值给客户类ClassB;
示例
>>> class SuperMeta(type):
def __call__(meta,classname,supers,classdict):
print('调用 SuperMeta.call:',
'meta: %s' % meta,
'classname: %s' % classname,
'supers: %s' % supers,
'classdict: %s' % classdict,sep='\n')
return type.__call__(meta,classname,supers,classdict)
>>> class SubMeta(type,metaclass=SuperMeta):
def __new__(meta,classname,supers,classdict):
print('调用 SubMeta.new:',
'meta: %s' % meta,
'classname: %s' % classname,
'supers: %s' % supers,
'classdict: %s' % classdict,sep='\n')
return type.__new__(meta,classname,supers,classdict)
def __init__(Class,classname,supers,classdict):
print('调用 SubMeta.init:',
'Class: %s' % Class,
'classname: %s' % classname,
'supers: %s' % supers,
'classdict: %s' % classdict,sep='\n')
print('初始化类对象:',list(Class.__dict__.keys()))
>>> class ClassA:pass
>>> class ClassB(ClassA,metaclass=SubMeta):
name='梯阅线条'
def meth(self,arg):
pass
调用 SuperMeta.call:
meta: <class '__main__.SubMeta'>
classname: ClassB
supers: <class '__main__.ClassA'>
classdict: {'__module__': '__main__', '__qualname__': 'ClassB', 'name': '梯阅线条', 'meth': <function ClassB.meth at 0x0000021485ECA3A0>}
调用 SubMeta.new:
meta: <class '__main__.SubMeta'>
classname: ClassB
supers: <class '__main__.ClassA'>
classdict: {'__module__': '__main__', '__qualname__': 'ClassB', 'name': '梯阅线条', 'meth': <function ClassB.meth at 0x0000021485ECA3A0>}
调用 SubMeta.init:
Class: <class '__main__.ClassB'>
classname: ClassB
supers: <class '__main__.ClassA'>
classdict: {'__module__': '__main__', '__qualname__': 'ClassB', 'name': '梯阅线条', 'meth': <function ClassB.meth at 0x0000021485ECA3A0>}
初始化类对象: ['__module__', 'name', 'meth', '__doc__']
>>> cb=ClassB()
>>> cb.name
'梯阅线条'
>>> type(SubMeta)
<class '__main__.SuperMeta'>
>>> type(SuperMeta)
<class 'type'>
>>> type(ClassB)
<class '__main__.SubMeta'>
>>> type(cb)
<class '__main__.ClassB'>
1.3 用常规类重载类创建调用
用法
# 定义
class SuperMeta:
def __call__(self,classname,supers,classdict):
Class=self.__New__(classname,supers,classdict)
self.__Init__(Class,classname,supers,classdict)
pass
return Class
class SubMeta(SuperMeta):
def __New__(self,classname,supers,classdict):
pass
return type(classname,supers,classdict)
def __Init__(self,Class,classname,supers,classdict):
pass
# 使用
class ClassA:pass
class ClassB(ClassA,metaclass=SubMeta()):pass
描述
通过常规类模拟元类的元类,重载__call__()方法,调用子类的New方法,New显式调用type()创建类对象赋值给客户类。
(1) 定义常规类SuperMeta模拟元类的元类;
(2) SuperMeta定义__call__()方法,调用子类SubMeta的__New__()和__Init__()方法;
(3) SuperMeta返回客户类Class;
(4) 定义常规类SubMeta,继承SuperMeta,作为客户类的元类;
(5) SubMeta的__New__()方法,显式调用type()方法创建类对象,返回赋值给客户类;
(6) SubMeta的__Init__()方法,对类对象进行初始化;
(7) 定义客户类ClassB,指定元类metaclass=SubMeta()实例对象;
(8) class协议自动调用实例对象SubMeta()的__call__()方法,搜索到SuperMeta的__call__()方法,触发元类SubMeta的New和Init方法;文章来源:https://www.toymoban.com/news/detail-807226.html
示例
>>> class SuperMeta:
def __call__(self,classname,supers,classdict):
print('调用 SuperMeta.call:',
'classname: %s' % classname,
'supers: %s' % supers,
'classdict: %s' % classdict,sep='\n')
Class=self.__New__(classname,supers,classdict)
self.__Init__(Class,classname,supers,classdict)
return Class
>>> class SubMeta(SuperMeta):
def __New__(self,classname,supers,classdict):
print('调用 SubMeta.new:',
'classname: %s' % classname,
'supers: %s' % supers,
'classdict: %s' % classdict,sep='\n')
return type(classname,supers,classdict)
def __Init__(self,Class,classname,supers,classdict):
print('调用 SubMeta.init:',
'Class: %s' % Class,
'classname: %s' % classname,
'supers: %s' % supers,
'classdict: %s' % classdict,sep='\n')
print('初始化类对象:',list(Class.__dict__.keys()))
>>> class ClassA:pass
>>> class ClassB(ClassA,metaclass=SubMeta()):
name='梯阅线条'
def meth(self,arg):
pass
调用 SuperMeta.call:
classname: ClassB
supers: <class '__main__.ClassA'>
classdict: {'__module__': '__main__', '__qualname__': 'ClassB', 'name': '梯阅线条', 'meth': <function ClassB.meth at 0x0000016DC8ADD1F0>}
调用 SubMeta.new:
classname: ClassB
supers: <class '__main__.ClassA'>
classdict: {'__module__': '__main__', '__qualname__': 'ClassB', 'name': '梯阅线条', 'meth': <function ClassB.meth at 0x0000016DC8ADD1F0>}
调用 SubMeta.init:
Class: <class '__main__.ClassB'>
classname: ClassB
supers: <class '__main__.ClassA'>
classdict: {'__module__': '__main__', '__qualname__': 'ClassB', 'name': '梯阅线条', 'meth': <function ClassB.meth at 0x0000016DC8ADD1F0>}
初始化类对象: ['__module__', 'name', 'meth', '__doc__']
>>> cb=ClassB()
>>> cb.name
'梯阅线条'
>>> type(SubMeta)
<class 'type'>
>>> type(SuperMeta)
<class 'type'>
>>> type(ClassB)
<class 'type'>
>>> type(cb)
<class '__main__.ClassB'>
到了这里,关于python通过函数和常规类编写元类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!