一、什么是元类
元类:就是生成类的的类,或者说是类的模版。
1 #定义一个类来看一下
2 class Meanwey:
3 pass
4 m = Meanwey()
5
6 #通过type来查看对象的类
7 print(type(m)) #<class '__main__.Meanwey'> m这个对象是属于Meanwey这个类
8
9 #类本身也是对象,所以可以用type来查看
10 print(type(Meanwey)) #<class 'type'> Meanwey这个类对象属于type这个类
通过上述简单代码可以看到,默认元类就是type。
二、所以可以用type这个元类来生成类
语法:想要生成的类名 = type(想要生成的类名,(继承的类默认objec,),属性字典{'x':1})。
注意:type中有三个参数,第一个参数是想要生成的类名为字符串类型;第二个参数是继承的类默认为obje为元组类型;第三个参数为生成的类的属性字典为字典类型。
1 Meanwey = type('Meanwey',(object,),{'name':'Meanwey'})
2 m1 = Meanwey()
3 print(type(m1)) #<class '__main__.Meanwey'>
4 print(type(Meanwey)) #<class 'type'>
5
6 # 可以看到通过type来生成的类和class关键字生成的类一样
7 # 当然也可以给类添加函数(方法)属性,则需要在type语句前先定义好函数(方法),然后在type的第三个参数添中加上函数属性和函数名
8
9 def __init__(self,name,age): #添加构造函数
10 self.name = name
11 self.age = age
12 def test(self):
13 print('调用了test方法')
14
15 Meanwey = type('Meanwey',(object,),{'name':'Meanwey','__init__':__init__,'test':test}) #加上函数属性
16 m1 = Meanwey('小明同学',24) #因为上面定义了构造函数__init__需要name,age两个参数,所以在实例化的时候需要传入
17 # print(type(m1)) #<class '__main__.Meanwey'>
18 # print(type(Meanwey)) #<class 'type'>
19
20 #查看初始化构造函数是否成功
21 print(m1.__dict__) #{'name': '小明同学', 'age': 24}
22
23 #调用test函数
24 m1.test() #调用了test方法
三、自定制元类
一个类没有声明自己的元类,默认他的元类就是type,除了使用内置元类type,我们也可以通过继承type来自定义元类,然后使用metaclass关键字参数为一个类指定元类。
1 #自定义元类
2 class Meta_Type(type):
3 def __call__(self,*args,**kwargs):
4
5 #self是Meta_Type的实例,也就是Foo
6 #因为每个类都默认继承object,所以可以调用__new__(Foo)方法,来实例化一个对象f1 == object.__new__(Foo) ==> f1
7 obj = object.__new__(self)
8
9 #调用Foo的构造函数实例化对象 == Foo.__init__(f1,*args,**kwargs)
10 self.__init__(obj,*args,**kwargs)
11
12 #最后要返回f1这个对象
13 return obj
14
15 #metaclass = Meta_Type ====> 会触发Foo = Meta_Type(Foo,'Foo',(),{}) ===>会触发Meta_Type的 __init__
16 class Foo(metaclass=Meta_Type):
17 def __init__(self,name):
18 self.name = name
19
20 #当Foo()时,表示执行了Foo,则会调用元类的__call__,__call__中会生成对象f1,并且调用Foo下的__init__方法,最终完成实例化
21 f1 = Foo('Menawey')
22
23 #>>>我是元类
24
25 print(f1.__dict__)
26 #>>>{'name': 'Menawey'}