Python----面向对象---自定义元类控制类的实例化行为的应用
一、单例模式
1 class Mysql: 2 def __init__(self): 3 self.host = '127.0.0.1' 4 self.port = 3306 5 6 7 obj1 = Mysql() 8 obj2 = Mysql() 9 10 print(obj1) 11 print(obj2) 12 13 结果为: 14 15 <__main__.Mysql object at 0x0000021CBF4DB588> 16 <__main__.Mysql object at 0x0000021CBF4DB160>
可以看出,两个对象的内存地址不一样,但是对象的属性是一样的,能不能只实例化一次,然后其它对象都引用它,就像a =1 b =1 ,,我们发现,他们指向的是同一块内存地址,答案是可以的,这就是单例模式,
1 class Mysql: 2 __instance = None 3 4 def __init__(self): 5 self.host = '127.0.0.1' 6 self.port = 3306 7 8 @classmethod 9 def singleton(cls): 10 print(cls) 11 if not cls.__instance: 12 obj = cls() 13 cls.__instance = obj 14 return cls.__instance 15 16 def conn(self): 17 pass 18 19 def execute(self): 20 pass 21 22 23 # obj1 = Mysql() 24 # obj2 = Mysql() 25 # 26 # print(obj1) 27 # print(obj2) 28 29 obj1 = Mysql.singleton() 30 obj2 = Mysql.singleton() 31 obj3 = Mysql.singleton() 32 33 print(obj1 is obj2 is obj3) 34 35 结果为; 36 37 <class '__main__.Mysql'> 38 <class '__main__.Mysql'> 39 <class '__main__.Mysql'> 40 True
以上就是实现单例模式的一种方式,class,下面介绍第二种方式,通过元类实现单例模式
实现方式2: 元类的方式
代码如下:
1 class Mymeta(type): 2 def __init__(cls, class_name, class_bases, class_dic): 3 4 if not class_name.istitle(): 5 raise TypeError('类名的首字母必须大写') 6 7 if '__doc__' not in class_dic or not class_dic['__doc__'].strip(): 8 raise TypeError('必须有注释,且注释不能为空') 9 10 super(Mymeta, cls).__init__(class_name, class_bases, class_dic) 11 cls.__instance = None 12 13 def __call__(cls, *args, **kwargs): 14 if not cls.__instance: 15 obj = object.__new__(cls) 16 cls.__init__(obj) 17 cls.__instance = obj 18 19 return cls.__instance 20 21 22 class Mysql(object, metaclass=Mymeta): 23 ''' 24 xxxx 25 ''' 26 def __init__(self): 27 self.host = '127.0.0.1' 28 self.port = 3306 29 30 def conn(self): 31 pass 32 33 def execute(self): 34 pass 35 36 37 obj1 = Mysql() 38 obj2 = Mysql() 39 obj3 = Mysql() 40 41 print(obj1 is obj2 is obj3) 42 43 结果为: 44 45 True
结果为True,实现了单例模式