python 之元类
定义类的两种方法:
1.class定义
2.type(类名,类的基类们,类的名称空间)
# 定义类的三要素:类名、基类、名称空间 class_name = 'Chinese' class_bases = (object,) class_body = """ country = 'China' def __init__(self,namem,age): self.name=namem self.age=age def talk(self): print('%s is talking'%self.name) """ class_dic = {} exec(class_body,globals(),class_dic) print(class_dic) Chinese = type(class_name,class_bases,class_dic)
自定义元类控制类的创建(在元类的init方法里做控制):
class Mymeta(type): ''' 自定义的元类 ''' def __init__(self,class_name,class_bases,class_dic): if not class_name.istitle(): raise TypeError('类名的首字母必须大写') # 不写注释时,则无__doc__ if '__doc__' not in class_dic or not class_dic['__doc__'].strip(): raise TypeError('必须有注释,且注释不能为空') super(Mymeta,self).__init__(class_name,class_bases,class_dic) class Chinese(object,metaclass=type): country = 'China' def __init__(self, namem, age): self.name = namem self.age = age def talk(self): print('%s is talking' % self.name) # Chinese首字母不大写的话会报异常 class Chinese1(object,metaclass=Mymeta): ''' 注释 ''' country = 'China' def __init__(self, namem, age): self.name = namem self.age = age def talk(self): print('%s is talking' % self.name) # Chinese2 = Mymeta(class_name,class_bases,class_dic)
自定义元类控制类的实例化(重写call方法):
class Mymeta(type): def __init__(self,class_name,class_bases,class_dic): if not class_name.istitle(): raise TypeError('类名的首字母必须大写') # 不写注释时,则无__doc__ if '__doc__' not in class_dic or not class_dic['__doc__'].strip(): raise TypeError('必须有注释,且注释不能为空') super(Mymeta,self).__init__(class_name,class_bases,class_dic) self.__instance = None
# 实现的单例可与sigleton装饰器的比较下 def __call__(self, *args, **kwargs): if not self.__instance: obj = object.__new__(self) self.__init__(obj) self.__instance = obj return self.__instance class Mysql(object,metaclass=Mymeta): ''' 元类控制实例化行为 ''' def __init__(self): self.host = '127.0.0.1' self.port = 3306 def conn(self): pass def execute(self): pass obj1 = Mysql() obj2 = Mysql() print(obj1 == obj2)