2019年10月4日 元类
metaclass 元类
元类是类的类,是类的模版。
元类是用来控制如何创建类的,正如类是创建对象的模版一样
元类的实例为类。
type事python的一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是type类实例化的对象。
class Foo: pass f1=Foo() #f1是通过Foo类实例化的对象 print(type(f1))#用type函数查看是谁的类 print(type(Foo))#类的类就是type def __init__(self,name,age):#如果需要再type中增加构造函数,就需要将函数放到最外面 self.name=name self.age=age FFo=type('FFo',(object,),{'x':1,'__init__':__init__}) #用type生成类,第一个事类名,第二个元祖形式是父类,因为是新式类所以父类默认就是object,后面是用字典形式表达参数 print(FFo) f1=FFo('SXJ',11) print(f1.__dict__)
>>>>
<class '__main__.Foo'>
<class 'type'>
<class '__main__.FFo'>
{'name': 'SXJ', 'age': 11}
可以通过继承type来自定义元类。
class MyType(type): #定义元类 def __init__(self,a,b,c): print('元类构造函数执行') print(self,'\n',a,'\n',b,'\n',c) #self 就是元类mytype的实例,也就是Foo def __call__(self, *args, **kwargs): print('>>>>>') print(self) print(args,kwargs) obj=object.__new__(self) #创建一个新对象 objcet.__new__(Foo) 这一步就是产生F1的 self.__init__(obj,*args, **kwargs)# 就是在调用Foo.__init__()把Foo内的init中的参数原封不动的传过去 print(obj) return obj #返回值赋予给F1 class Foo(metaclass=MyType):#声明元类 Foo=Mytype('Foo',(object,),{'name':name}),传递了4个参数给Mytype,触发init方法,所以mytype中的init需要4个参数 def __init__(self,name): self.name=name #f1.name=name f1=Foo('sxj') #实例化会触发init 和call print(f1.__dict__)
>>>>
元类构造函数执行
<class '__main__.Foo'>
Foo
()
{'__module__': '__main__', '__qualname__': 'Foo', '__init__': <function Foo.__init__ at 0x10219d0d0>}
>>>>>
<class '__main__.Foo'>
('sxj',) {}
<__main__.Foo object at 0x102176f98>
{'name': 'sxj'}
精简版
class MyType(type): #定义元类 def __init__(self,a,b,c): print('元类构造函数执行') def __call__(self, *args, **kwargs): obj=object.__new__(self) #创建一个新对象 objcet.__new__(Foo) 这一步就是产生F1的 self.__init__(obj,*args, **kwargs)# 就是在调用Foo.__init__()把Foo内的init中的参数原封不动的传过去 return obj #返回值赋予给F1 class Foo(metaclass=MyType):#声明元类 Foo=Mytype('Foo',(object,),{'name':name}),传递了4个参数给Mytype,触发init方法,所以mytype中的init需要4个参数 def __init__(self,name): self.name=name #f1.name=name f1=Foo('sxj') #实例化会触发init 和call