美文网首页
Python3 & 使用__new__实现单例模式

Python3 & 使用__new__实现单例模式

作者: 乘风破浪的姐姐 | 来源:发表于2020-12-08 18:50 被阅读0次

    单例设计模式概念

    设计模式,是对工作的总结和提练,目的是提高代码的可重用性及可靠性。
    单例设计模式,是指让类创建的对象,在系统中只有 唯一的一个实例。且每一次执行 类名() 返回的对象,内存地址是相同的。这种模式一般应用在 例如:打印机,视频播放等应用上。

    new 方法

    使用 类名() 创建对象时,Python 的解释器 首先 会 调用 new 方法为对象 分配空间。new 是一个 由 object 基类提供的 内置的静态方法,主要作用有两个:

    1. 在内存中为对象 分配空间
    2. 返回 对象的引用
      示例:
    class PrintPlayer(object):
        def __new__(cls, *args, **kwargs):
            print("__new__")
    
        def __init__(self):
            print("初始化打印机对象....")
    
    prints = PrintPlayer()
    print(prints)
    

    输出结果:

    __new__
    None
    

    可以看到,上述示例中,new没有返回对象的引用,所以在打印实例化对象时,返回了 None

    正确的写法应该是

    class PrintPlayer(object):
        def __new__(cls, *args, **kwargs):
            return super().__new__(cls)
    
        def __init__(self):
            print("初始化打印机对象....")
    
    prints = PrintPlayer()
    print(prints)
    

    输出结果:

    初始化打印机对象....
    <__main__.PrintPlayer object at 0x000002329A47E7C0>
    

    Python 中的单例模式

    所谓单例,是让类在系统中创建唯一的一个实例,那么如何做到呢?
    步骤分析:
    1)定义一个 类属性,初始值是 None,用于记录 单例对象的引用
    2)重写 new 方法
    3)如果 类属性 is None,调用父类方法分配空间,并在类属性中记录结果
    4)返回 类属性 中记录的 对象引用
    代码:

    class PrintPlayer(object):
        instance = None
        def __new__(cls, *args, **kwargs):
            if cls.instance is None:
                cls.instance = super().__new__(cls)
    
            return cls.instance
    
        def __init__(self):
            print("初始化打印机对象....")
    
    prints1 = PrintPlayer()
    print(prints1)
    
    prints2= PrintPlayer()
    print(prints2)
    

    输出:

    初始化打印机对象....
    <__main__.PrintPlayer object at 0x000002776F59E7C0>
    初始化打印机对象....
    <__main__.PrintPlayer object at 0x000002776F59E7C0>
    

    可以看出,在每次使用 类名() 创建对象时,Python 的解释器都会自动调用两个方法:new 分配空间,init 对象初始化。所以实例化两次,会调用init方法两次初始化。
    那么如何让 初始化动作 只被 执行一次呢?

    解决方法:
    1)定义一个类属性 init_flag 标记是否 执行过初始化动作,初始值为 False
    2)在 init 方法中,判断 init_flag,如果为 False 就执行初始化动作
    3)然后将 init_flag 设置为 True
    这样,再次 自动 调用 init 方法时,初始化动作就不会被再次执行 了
    代码:

    class PrintPlayer(object):
        instance = None
        init_flag = False
        def __new__(cls, *args, **kwargs):
            if cls.instance is None:
                cls.instance = super().__new__(cls)
    
            return cls.instance
    
        def __init__(self):
            if not PrintPlayer.init_flag :
                print("初始化打印机对象....")
                PrintPlayer.init_flag = True
    
    prints1 = PrintPlayer()
    print(prints1)
    
    prints2= PrintPlayer()
    print(prints2)
    

    输出:

     初始化打印机对象....
    <__main__.PrintPlayer object at 0x000001E8E23CE7C0>
    <__main__.PrintPlayer object at 0x000001E8E23CE7C0>
    

    相关文章

      网友评论

          本文标题:Python3 & 使用__new__实现单例模式

          本文链接:https://www.haomeiwen.com/subject/mupywktx.html