一、元类知识补充
1.1 自定义元类
义元类:继承type
class Mymeta(type):
def __init__(self,name,bases,dic):
#self 是Person 这个类(对象)
#在这个位置,其实self也就说Person这个类,内部已经有东西了,名称空间已经有东西了
#所以在这个地方,可以通过dic来判断名称空间
#也可以直接通过self.__dict__/self.属性 来判断
a=dic.get('name')
if not a :
raise Exception('没有name属性,不能创建')
# def __call__(self, *args, **kwargs):
# pass
class Person(metaclass=Mymeta): #Person=Mymeta('Person',(object,),{...}) Mymeta类实例化,会把三个参数传到Mymeta的__init__方法中
# class Person(): #Person=Mymeta('Person',(object,),{...}) Mymeta类实例化,会把三个参数传到Mymeta的__init__方法中
def __init__(self,name):
self.name=name
raise Exception('就不让你创建')
p=Person('lqz') #自动触发Person类__init__的执行
总结:可以通过自定义元类,重写__init__方法来控制类的产生
1.2 控制对象产生
#模板:控制对象的产生
class Mymeta(type):
def __call__(self, *args, **kwargs):
obj=object.__new__(self)
obj.__init__(*args, **kwargs)
return obj
class Person(metaclass=Mymeta):
def __init__(self,name):
self.name=name
def __call__(self, *args, **kwargs):
print('xxx')
p=Person('lqz')
注意:
#object.__new__ 传哪个类就得到哪个类的空对象
#__new__和__init__的区别
#__new__ 创建空对象
#__init__ 初始化空对象
#object.__new__(Person) :生成Person类的对象 空的
#type.__new__(cls,name,bases,dic) :生了cls这个类对象,里面有东西
#元类中
#__init__:控制类的产生,在__new__之后
#__call__:对着对象的产生
#__new__:控制类产生最根上,其实本质最根上也不是它,是type的__call__,但是我们控制不了了
二、单例模式
2.1 什么是设计模式
设计模式是面对各种问题进行提炼和抽象而形成的解决方案。这些设计方案是前人不断试验,考虑了封装性、复用性、效率、可修改、可移植等各种因素的高度总结。它不限于一种特定的语言,它是一种解决问题的思想和方法。
2.2 为什么用设计模式
公司人事会有变动,程序员也会成长。不管是哪种情况,代码非常有可能会被移交,即代码的编写者和维护者很有可能会是不同的人。那么代码的可读性就显得非常重要了。由于高级语言的出现,让机器读懂你的意图已经不是最主要的“矛盾”,而让人读懂你的意图才是最重要。按照设计模式编写的代码,其可读性也会大大提升,利于团队项目的继承和扩展。
2.4设计模式分类
设计模式可以分为三个大类:创建类设计模式、结构类设计模式、行为类设计模式。
创建类模式:单例模式、工厂模式(简单工厂模式、抽象工厂模式)、建造者模式、原型模式。
结构类模式:代理模式、装饰器模式、适配器模式、门面模式、组合模式、享元模式、桥梁模式。
行为类模式:策略模式、责任链模式、命令模式、中介者模式、模板模式、迭代器模式、访问者模式、观察者模式、解释器模式、备忘录模式、状态模式。
设计模式也衍生出了很多的新的种类,不局限于这23种
2.5 什么是单例模式
单例模式是所有设计模式中比较简单的一类,其定义如下:Ensure a class has only one instance, and provide a global point of access to it.(保证某一个类只有一个实例,而且在全局只有一个访问点)
2.6单例模式优点
1、由于单例模式要求在全局内只有一个实例,因而可以节省比较多的内存空间;
2、全局只有一个接入点,可以更好地进行数据同步控制,避免多重占用;
3、单例可长驻内存,减少系统开销
2.7单例模式缺点
1、单例模式的扩展是比较困难的;
2、赋于了单例以太多的职责,某种程度上违反单一职责原则(六大原则后面会讲到);
3、单例模式是并发协作软件模块中需要最先完成的,因而其不利于测试;
4、单例模式在某种情况下会导致“资源瓶颈”。
2.8单例模式应用
1、生成全局惟一的序列号;
2、访问全局复用的惟一资源,如磁盘、总线等;
3、单个对象占用的资源过多,如数据库等;
4、系统全局统一管理,如Windows下的Task Manager;
5、网站计数器。
三、单例模式的四种方法
3.1 绑定方法
class Single:
_test = None
def __init__(self,pore,host):
self.pore = pore
self.host = host
@classmethod
def get_sing(cls):
import settings
if not cls._test:
cls._test = cls(settings.pore,settings.host)
return cls._test
3.2 装饰器方法
def get_sing(cls):
_test = None
def wrapper(*args,**kwargs):
if len(args) != 0 or len(kwargs) != 0:
res = cls(*args,**kwargs)
return res
else:
import settings
nonlocal _test
if not _test:
_test = cls(settings.pore,settings.host)
return _test
return wrapper()
@get_sing
class Single():
def __init__(self,pore,host):
self.pore = pore
self.host = host
3.3 通过元类方法
class Mymeta(type):
def __init__(self,name,bases,dic):
import settings
self._test = self(settings.pore,settings.host)
def __call__(self,*args,**kwargs):
if len(args) != 0 or len(kwargs) != 0:
obj = object.__new__(self)
obj.__init__(*args,**kwargs)
return obj
else:
return self._test
class Single():
def __init__(self,pore,host):
self.pore = pore
self.host = host
3.4 导入模块方法
def test():
from signal import s1
print(s1)
def test2():
from signal import s1 as s2
print(s2)