啰嗦一下:
必须再次申明类(class) 是被创建出来的,由type类的__call__创建 : class x = type('x',x.__bases__,{classdict}) .
如果类涉及了继承以及元类 那么 class Person(继承类 ,... metaclass = 元类);
下面有一个例子是元类也能做到像装饰器一样,
但需要说明的是,装饰器在执行代码的时候, 类已经创建完成了,而元类则是创建类的过程
下面代码中的元类都重载了__new__ ,而没有重载元类的__init__
原因是元类的__new__ 调用完后class已经创建完毕,
而元类的__init__ 跟使用类装饰器来修改class没什么区别了 : 元类与装饰器的混合应用
#任何一个可调用的对象就可以作为元类,不必非得是一个继承type的类.
#可以用一个函数假装成元类
def meta_func(classname, bases , classDict):
print('call meta_func:',classname,bases,classDict , sep='\n')
return type(classname,bases,classDict) #还是由type函数来创建类对象
class Person(metaclass=meta_func):
person_data = 123
def __init__(self):
print('__init__')
有个细节需要注意(即方法的查找,这里可能太细微了,平常根本不需要注意) .另元类本身并不创建实例 :
#2个元类, 重复一下,元类本身不创建实例
class super_meta(type): #顶层元类 ,重定义__call__
def __call__(self, *args, **kwargs):
print('Super_meta __call__ :',self,args,kwargs,sep='\n')
aClass = type.__call__(self,*args,**kwargs) #返回已经创建的类对象(并不是元类对象!!!)
print('->>>>>Super_meta class 创建完成:',aClass)
return aClass
#还是一个元类, 元类本身还可以有元类,可元类并不会被实例化!!!
class sub_meta(type,metaclass=super_meta):
def __new__(cls, *args, **kwargs): #重定义__new__
print('sub_meta __new__:',cls, args,kwargs,sep='\n')
return type.__new__(cls,*args,**kwargs) #调用父类的__new__
def __init__(self,*args,**kwargs): #重定义__init__
print('sub_meta __init__:',self,args,kwargs,sep='\n')
#这2个类没有任何输出,反证了元类本身并不会被实例化,这里需要注意的是__call__的调用, 元类的查找过程与一般类的继承查找方式不一样.因为元类不会被实例化
#class Person(metaclass=sub_meta):
# person_data = 123
# def method(self):
# print('Person.method')
#这部分被注释的代码,其执行流程是
#Person 会被sub_meta 创建, 调用Super_meta的__call__
#Super_meta的__call__ 将调用sub_meta的__new__ , __init__
前面说了,不是非得是type的子类才能作为元类,只要是可调用的对象都可以,自己实现一个假的元类:
#一个可调用的对象(__call__),就可以实现一个元类
#自定义2个函数 New , Init 模拟 __new__ , __init__ 过程
class Meta:
def __New__(self,*args,**kwargs):
print('Meta __New__:',self,args,kwargs,sep='\n')
return type(*args,**kwargs)
def __Init__(self,*args,**kwargs):
print('Meta __init__:',self,args,kwargs,sep='\n')
def __call__(self, *args, **kwargs):
print('Meta __call__:',self,args,kwargs,sep='\n')
aClass = self.__New__(*args,**kwargs)
print('Class生成了:',aClass)
self.__Init__(aClass,*args,**kwargs)
return aClass
class Person(metaclass=Meta()): #注意这里是Meta() ,是一个实例, 否则__call__ 无法被调用,而如果是type子类则不需要
person_data = 123
def __init__(self):
print('Person __init__')
元类与继承:
元类是创建类的一个类 . 当父类有元类声明时, 子类也会由该元类创建
class Meta1(type):
def __new__(cls, *args, **kwargs):
print('meta1 __new__ : ' , args)
return type.__new__(cls,*args,**kwargs)
def toast(cls):
print('toast')
#父类指定了元类
class Super(metaclass=Meta1):
def sp(self):
print('super')
#子类继承父类, 那么子类也会由父类指定的元类创建
class sub(Super):
def sb(self):
print('sub')
#echo:
#meta1 __new__ : ('Super', (), {'__module__': '__main__', '__qualname__': 'Super', 'sp': <function Super.sp at 0x0200EAE0>})
#meta1 __new__ : ('sub', (<class '__main__.Super'>,), {'__module__': '__main__', '__qualname__': 'sub', 'sb': <function sub.sb at 0x0200EA98>})
#注意
s = sub()
#s.toast() 将出错.实例的属性查找只会搜索自身以及实例.__class__及其父类们的__dict__ ,元类不包含在其中!!
再声明一下,元类只是创建类的一个玩意
接下来,看看基于元类的一些扩展类的方式:
#基于元类扩展类.
#把一下2个函数添加进类中, 方式有很多
# 可以直接添加 :className.xx = some_func
# 可以用装饰器 :def decorator(aClass):aClass.xx = some_func ; return aClass
# 这里使用元类来实现
def first_func(obj):
print( obj.value * 2)
def sec_func(obj):
print(obj.value * 3)
class ExtendMetaClass(type): #元类定义,继承type
def __new__(meta, classname,bases, classdict):
classdict['first_func'] = first_func #在命名空间词典中添加2个属性,指向2个函数
classdict['sec_func'] = sec_func
print('__new__ :',meta, classname,bases, classdict)
return type.__new__(meta,classname,bases,classdict)
class client1(metaclass=ExtendMetaClass): #使用元类来创建client1 类对象
def __init__(self,value = 2):
self.value = value
def x(self):
return self.value ** 2
class client2(metaclass=ExtendMetaClass): #使用元类来创建client2类对象
value = 123
c = client1()
c.first_func()
c.sec_func()
#echo:
#__new__ : <class '__main__.ExtendMetaClass'> client1 () {'__module__': '__main__', '__qualname__': 'client1', '__init__': <function client1.__init__ at 0x01FEDBB8>, 'x': <function client1.x at 0x01FEDB70>, 'first_func': <function first_func at 0x01FEDED0>, 'sec_func': <function sec_func at 0x01FEDC90>}
#__new__ : <class '__main__.ExtendMetaClass'> client2 () {'__module__': '__main__', '__qualname__': 'client2', 'value': 123, 'first_func': <function first_func at 0x01FEDED0>, 'sec_func': <function sec_func at 0x01FEDC90>}
#4
#6
*元类基本上是用来管理类本身的(在创建/初始化类对象的时候做一些事) .
但是也可以像装饰器一样使用元类(这并不是一种好的用法,先声明下,这种做法比较隐晦):
#把元类假装成装饰器来使用;
#注意:这个例子实际不太好,只是用来扩展元类的用法.这种用法比较隐晦
def tracer(*args):
print('创建Person类对象')
aClass = type(*args) #利用type来创建Person类对象
print('创建Person完成:',aClass)
class Wrapper: #内部类 ,默认使用type 创建Wrapper 类对象
def __init__(self,*args,**kwargs):
self.wrapper = aClass(*args,**kwargs) #实例对象添加一个属性,把Person实例嵌入
def __getattr__(self, attr):
print('tracer:',attr)
return getattr(self.wrapper,attr)
return Wrapper #返回由type创建的Wrapper
class Person(metaclass=tracer): #此时这个Person 已经是Wrapper了,Wrapper由type创建s
def __init__(self,name='Person',age=10):
self.name = name
self.age = age
def display(self):
print(self.name,self.age)
print('现在的Person是什么:',Person) #<class '__main__.tracer.<locals>.Wrapper'>
p = Person()
p.display()
#echo:
#创建Person类对象
#创建Person完成: <class '__main__.Person'>
#现在的Person是什么: <class '__main__.tracer.<locals>.Wrapper'>
#tracer: display
#Person 10