【问题标题】:two issues on the lazy instantiation in the Singleton pattern关于 Singleton 模式中惰性实例化的两个问题
【发布时间】:2021-10-18 09:08:56
【问题描述】:

我的python版本:

python3 --version
Python 3.9.2

问题 1:
isinstance函数是什么意思?

class Singleton1(object):
    __instance = None
    def __init__(self):
        if not hasattr(Singleton1, '__instance'):
            print("__init__ method called, but no instance created")
        else:
            print("instance already created:", self.__instance)
    @classmethod
    def get_instance(cls):
        if not cls.__instance:
            cls.__instance = Singleton1()
        return cls.__instance

初始化它:

x = Singleton1()
__init__ method called, but no instance created

检查isinstance函数:

isinstance(x,Singleton1)
True

如果x不是实例,为什么isinstance(x,Singleton1)说它是Singleton1的实例?

问题2:
为什么__init__方法还是不能调用?

现在将Singleton1 类中的所有__instance(双下划线)替换为_instance(单下划线),并将所有Singleton1 替换为Singleton2

class Singleton2(object):
    _instance = None
    def __init__(self):
        if not hasattr(Singleton2, '_instance'):
            print("__init__ method called, but no instance created")
        else:
            print("instance already created:", self._instance)
    @classmethod
    def get_instance(cls):
        if not cls._instance:
            cls._instance = Singleton2()
        return cls._instance

初始化它:

y = Singleton2()
instance already created: None

为什么__init__方法在这种状态下无论如何都不能调用?

@snakecharmerb on issue1,为什么有人说它是惰性实例化,如果 isinstance(x,Singleton1) 为真,则无需调用 Singleton1.get_instance() ,因为实例在实例化过程中已经创建。

【问题讨论】:

标签: python-3.x class singleton


【解决方案1】:

hasattr 检查并没有按照您的想法进行。使用Singleton2*hasattr(Singleton2, '_instance') 始终为True,因为该类有一个名为_instance 的属性。您想检查实例的 value,因此请改用 getattr;然后将打印预期的输出。

isinstance 检查成功,因为Singleton2() 每次都会返回一个新实例 - 没有什么可以阻止这一点。您可以添加 __new__ 方法来创建 _instance 并在每次调用 Singleton2() 时返回它。请注意,这意味着 _instance 在调用 __init__ 时将始终存在。

class Singleton2:

    _instance = None     
       
    def __new__(cls):    
        if cls._instance is not None:    
            return cls._instance    
        instance = super().__new__(cls)    
        cls._instance = instance    
        return instance 

*hasattr 签入 Singleton1 会因在 __instance 上执行的名称修改而变得复杂。一般来说,避免使用双下划线变量名,除非避免类层次结构中的名称冲突。

【讨论】:

  • 第一个问题怎么样?
  • 你是什么意思? x 是类的一个实例,所以isinstance 返回True。你认为不应该吗?
  • 为什么有人说是惰性实例化,如果isinstance(x,Singleton1)为真,就不用Singleton1.get_instance()调用了,因为实例化时已经创建好了。
  • 单例设计模式的目的是该类应该只有一个实例,因此实例化该类应该总是返回相同的实例。问题中的实现是惰性的,因为在调用 get_instance() 之前不会创建实例。通过直接实例化类来绕过get_instance() 的能力是实现中的一个缺陷。我已经演示了一种使用__new__ 解决此问题的方法。另请参阅this Q&A,了解在 Python 中创建单例的其他方法。
  • 我得到了一个明确的结论,它不能用我的两种方法创建一个惰性实例化,这是真的还是假的?
猜你喜欢
  • 1970-01-01
  • 2012-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多