python基础_元类
元类:
元类是类的类,元类主要是控制类是如何创建的,正如类控制对象如何创建一样。
type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是type类实例化的对象。
创建类的两种方式:
1.使用class关键字,
class Chinese(object): country='China' def __init__(self,name,age): self.name=name self.age=age def talk(self): print('%s is talking' %self.name)
2.手动创建,利用type实例化
#法一 class Foo: def __init__(self): pass print(Foo) print(Foo.__dict__) #法二: def __init__(self,name,age): self.name=name self.age=age def test(self): print('=====>') FFo=type('FFo',(object,),{'x':1,'__init__':__init__,'test':test}) print(FFo) print(FFo.__dict__) f1=FFo('alex',18) print(f1.name) f1.test() <class '__main__.Foo'> {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x00000168BA6456A8>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None} <class '__main__.FFo'> {'x': 1, '__init__': <function __init__ at 0x00000168BA042EA0>, 'test': <function test at 0x00000168BB67EEA0>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'FFo' objects>, '__weakref__': <attribute '__weakref__' of 'FFo' objects>, '__doc__': None} alex =====>
type 接收三个参数:
-
第 1 个参数是字符串 ‘Foo’,表示类名
-
第 2 个参数是元组 (object, ),表示所有的父类
-
第 3 个参数是字典,这里是一个空字典,表示没有定义属性和方法
补充:若Foo类有继承,即class Foo(Bar):.... 则等同于type('Foo',(Bar,),{})
自定义元类:
对象加括号,会默认执行产生该对象的类中的__call__方法。
class MyType(type): def __init__(self,a,b,c): print('初始化生成Foo类') def __call__(self, *args, **kwargs): obj=object.__new__(self) self.__init__(obj,*args,**kwargs) return obj class Foo(metaclass=MyType): def __init__(self,name): self.name=name print('初始化生成Foo类对象') 初始化生成Foo类 class MyType(type): def __init__(self,a,b,c): print('初始化生成Foo类') def __call__(self, *args, **kwargs): obj=object.__new__(self) #object.__new__(Foo)--->f1 self.__init__(obj,*args,**kwargs) return obj class Foo(metaclass=MyType): def __init__(self,name): self.name=name print('初始化生成Foo类对象') f1=Foo('alex') 初始化生成Foo类 初始化生成Foo类对象
第一次之所以打印:初始化生成Foo类,是因为在执行Foo类的__init__()时,触发了MyType的__init__()函数的内部命令执行,因为只有执行MyType的__init__()函数的内部命令,才算对MyType进行了实例化,才会有Foo这个类,才能执行它的__init__(),又是因为无需进行Foo实例化对象,所以无需执行Foo的__init__()内部的命令。
第二次之所以两句都打印了,是因为加了一句Foo实例化对象的语句。
加断点一句一句执行就会发现,在执行了f1=Foo('alex')之后转去执行了__call__()函数的内部,因为Foo是MyType的对象,所以Foo加上了()之后,要去执行所属类的__call__函数。
f1=object.__new__(Foo),Foo实例化化产生对象f1。