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

 

posted @ 2019-10-04 20:31  小圣庄  阅读(140)  评论(0编辑  收藏  举报