Python进阶-元类及自定制元类

一、什么是元类

元类:就是生成类的的类,或者说是类的模版。
动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的

比方说

#定义一个类来看一下
class Meanwey:
    pass
m = Meanwey()

#通过type来查看对象的类
print(type(m))                   
 #    m这个对象是属于Meanwey这个类

#类本身也是对象,所以可以用type来查看
print(type(Meanwey))           
 #   Meanwey这个类对象属于type这个类

通过上述简单代码可以看到,m是实例所以他的类型是Meanwey,而Meanweyclass他的类型是type所以可以看出来,默认元类就是type


二、所以可以用type这个元类来生成类
  • 语法:
    想要生成的类名 = type(想要生成的类名,(继承的类默认objec,),属性字典{'x':1})

注意:type中有三个参数,第一个参数是想要生成的类名为字符串类型;第二个参数是继承的类默认为obje为元组类型;第三个参数为生成的类的属性字典为字典类型。

Meanwey = type('Meanwey',(object,),{'name':'Meanwey'})
m1 = Meanwey()
print(type(m1))                    #        
print(type(Meanwey))            #
  • 可以看到通过type来生成的类和class关键字生成的类一样
  • 当然也可以给类添加函数(方法)属性,则需要在type语句前先定义好函数(方法),然后在type的第三个参数添中加上函数属性和函数名
def __init__(self,name,age):    #添加构造函数
    self.name = name    
    self.age = age
def test(self):
    print('调用了test方法')

Meanwey = type('Meanwey',(object,),{'name':'Meanwey','__init__':__init__,'test':test}) #加上函数属性
m1 = Meanwey('小明同学',24)  
#因为上面定义了构造函数__init__需要name,age两个参数,所以在实例化的时候需要传入
print(type(m1))                    #        
print(type(Meanwey))                #

#查看初始化构造函数是否成功
print(m1.__dict__)                    #{'name': '小明同学', 'age': 24}

#调用test函数
m1.test()                            #调用了test方法
三、自定制元类

一个类没有声明自己的元类,默认他的元类就是type,除了使用内置元类type,我们也可以通过继承type来自定义元类,然后使用metaclass关键字参数为一个类指定元类。

#自定义元类
class Meta_Type(type):
    def __call__(self,*args,**kwargs):

        #self是Meta_Type的实例,也就是Foo
        #因为每个类都默认继承object,所以可以调用__new__(Foo)方法,
        #来实例化一个对象f1 == object.__new__(Foo)  ==> f1
        obj = object.__new__(self)

        #调用Foo的构造函数实例化对象 == Foo.__init__(f1,*args,**kwargs)
        self.__init__(obj,*args,**kwargs)

        #最后要返回f1这个对象
        return obj

#metaclass = Meta_Type  ====> 会触发Foo = Meta_Type(Foo,'Foo',(),{})  
# ===>会触发Meta_Type的 __init__
class Foo(metaclass=Meta_Type):
    def __init__(self,name):
        self.name = name

#当Foo()时,表示执行了Foo,则会调用元类的__call__,__call__中会生成对象f1,
#并且调用Foo下的__init__方法,最终完成实例化
f1 = Foo('Menawey')

#>>>我是元类

print(f1.__dict__)
#>>>{'name': 'Menawey'}

你可能感兴趣的:(Python进阶-元类及自定制元类)