0%

35、单例模式.md

面向对象其它

一、单例模式

1、什么是设计模式

  1. 设计模式前人工作的总结和提炼,通常,被人们广泛流传的设计模式都是针对 某一特定问题的成熟的解决方案

  2. 使用 设计模式 是为了可重用代码、让代码更容易被他人理解、保证代码可靠性

2、单例设计模式

  1. 目的 —— 让 创建的对象,在系统中 只有 唯一的一个实例
  2. 每一次执行 类名() 返回的对象,内存地址是相同的

3、应用场景

4、如何创建单例模式

  1. 使用模块
  2. 使用装饰器
  3. 使用类
  4. 基于__new__方法实现(推荐使用,方便)
  5. 基于metaclass方式实现

1、使用模块

  1. 说明

    Python 的模块就是天然的单例模式 系统规定

    因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码

2、__new__ 方法

  1. 说明

    使用 类名() 创建对象时,Python 的解释器 首先 会 调用 __new__ 方法为对象 分配空间

    __new__是一个 由 object 基类提供的内置的静态方法,主要作用有两个:

    • 在内存中为对象 分配空间
    • 返回 对象的引用
    • Python 的解释器获得对象的 引用 后,将引用作为 第一个参数,传递给 __init__ 方法重写 __new__ 方法 的代码非常固定!
    • 重写 __new__ 方法 一定要 return super().__new__(cls)
    • 否则 Python 的解释器 得不到 分配了空间的 对象引用就不会调用对象的初始化方法

    注意:__new__ 是一个静态方法,在调用时需要 主动传递 cls 参数

  2. 举个栗子

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Singleton(object):
    __instance = None
    def __new__(cls, *args, **kwargs):
    if cls.__instance is None
    Singleton._instance = object.__new__(cls)
    return Singleton._instance

    def __init__(self):
    pass
    obj1 = Singleton()
    obj2 = Singleton()
    print(obj1,obj2)

3、使用装饰器

  1. 举个栗子

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    def singleton(cls, *args, **kwargs):
    instance = {}
    def _singleton():
    if cls not in instance:
    instance[cls] = cls(*args, **kwargs)
    return instance[cls]
    return _singleton

    @singleton
    class Singleton(object):
    def __init__(self):
    self.num_sum = 0

    def add(self):
    self.num_sum = 100
    if __name__ == '__main__':
    obj1 = Singleton()
    obj2 = Singleton()
    print(obj1, obj2)

4、使用类

  1. 举个栗子

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Singleton(object):
    __instance = None

    @classmethod
    def instance(cls, *args, **kwargs):
    if not hasattr(Singleton, "_instance"):
    Singleton.__instance = Singleton(*args, **kwargs)
    return Singleton.__instance

    obj1 = Singleton.instance()

    obj2 = Singleton.instance()

5、使用元类

  1. 举个栗子

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class SingletonType(type):
    def __init__(self,*args,**kwargs):
    super(SingletonType,self).__init__(*args,**kwargs)

    def __call__(cls, *args, **kwargs): # 这里的cls,即Singleton类
    print('cls',cls)
    obj = cls.__new__(cls,*args, **kwargs)
    cls.__init__(obj,*args, **kwargs) # Singleton.__init__(obj)
    return obj

    class Singleton(metaclass=SingletonType): # 指定创建Singleton的type为SingletonType
    def __init__(self,name):
    self.name = name
    def __new__(cls, *args, **kwargs):
    return object.__new__(cls)

    obj = Singleton('xx')

二、type和isinstance

1、概述

Python为每一个object在创建的时候就指定了一个内部类型,当我们不知道一个变量是什么类型时,就需要通过一些方法来输出变量的类型,Python的type函数提供了这样的功能。type()返回任意Python对象的类型,而不局限于标准类型。

那么在程序中如何判断类型并根据判断结果进行相应的处理呢?首先可以通过type和is来进行

2、举个栗子

  1. type来获取类型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    class Test:
    pass
    class Test2(Test):
    pass
    if __name__ == "__main__":
    x = 123 # int
    print(type(x))
    y = 3.1415 # float
    print(type(y))
    t1 = Test() # Test1
    print(type(t1))
    t2 = Test2() # Test2
    print(type(t2))
    s = 'sdf' # str
    print(type(s))
    b = True # bool
    print(type(b))
    li = ['s'] # list
    print(type(li))
    tup = ('sdf',) # tuple
    print(type(tup))
    dic = {'sdf': 132} # dict
    print(type(dic))
  2. type来获取类型判断类型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    class Test:
    pass

    class Test2(Test):
    pass

    if __name__ == "__main__":
    x = 123 # int
    print(type(x) is int)
    y = 3.1415 # float
    print(type(y) is float)
    t1 = Test() # Test1
    print(type(t1) is Test)
    t2 = Test2() # Test2
    print(type(t2) is Test2)
    s = 'sdf' # str
    print(type(s) is str)
    b = True # bool
    print(type(b) is bool)
    li = ['s'] # list
    print(type(li) is list)
    tup = ('sdf',) # tuple
    print(type(tup) is tuple)
    dic = {'sdf': 132} # dict
    print(type(dic) is dict)

  3. 通过instance方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class Test:
    pass
    class Test2(Test):
    pass
    if __name__ == "__main__":
    x = 123 # True
    print(isinstance(x, int))
    y = 3.1415 # True
    print(isinstance(y, float))
    t1 = Test() # True
    print(isinstance(t1, Test))
    t2 = Test2() # True
    print(isinstance(t2, Test))
    # False
    print(type(t2) is Test)

3、不同点

  1. type可以只接收一个参数,打印其未知的所属的类型;而isinstance只能判断是否属于某个已知类型
  2. isinstance可以判断子类对象是否继承于父类;而type不可以
  3. 应用场景不同;type主要用于获取未知变量的类型;isinstance主要用于判断A类是否继承于B类