Python单身人士行为怪异

Python Singleton acting weird

我想制作一个 python 单例 class 这样 class 的实例在代码中的其他地方调用 class 时完全相同节目开启后

我试图找到单例示例并从 link 中找到了一个:https://wikidocs.net/3693

class Singleton(object):
    _instance = None
    def __new__(class_, *args, **kwargs):
        if not isinstance(class_._instance, class_):
            class_._instance = object.__new__(class_, *args, **kwargs)
        return class_._instance

然后像这样测试

class Test(Singleton):
    def __init__(self, name=None):
        print(name)

test1 = Test('a')

期望显示初始化时给出的名称 但这给了我一个错误

TypeError                                 Traceback (most recent call last)
<ipython-input-55-f3383e846037> in <module>()
----> 1 test1 = Test('a')

<ipython-input-33-222ac7a13884> in __new__(class_, *args, **kwargs)
     27     def __new__(class_, *args, **kwargs):
     28         if not isinstance(class_._instance, class_):
---> 29             class_._instance = object.__new__(class_, *args, **kwargs)
     30         return class_._instance

TypeError: object() takes no parameters

但是当我尝试这个的时候,这个成功了

Test() # with no prarameter
test1 = Test('a') # this prints 'a' without error

我想知道如何解决这个问题。不然我启动程序的时候还得一开始就不带参数初始化

我想要获取参数的原因是,当参数在某个时候更改时,我想将更改后的信息应用到调用此参数的所有地方 class。

单例模式在 Python 中毫无意义。几乎总是,你最好使用模块。或者一些工厂功能作为你的主要结构 API,例如getLogger.

如果你真的坚持让你的class表面上成为单身人士(这总是可以被颠覆),我建议metaclass approach因为它side-steps 覆盖 __new__ 的各种并发症,尽管元 class 引入了它们自己的并发症。

但是为了解决您的问题,此代码已过时,将参数传递给 object.__new__ 现在将引发错误,而不是被简单地忽略。要实现此功能,只需 不要将任何参数传递给 __new__:

In [1]: class Singleton(object):
   ...:     _instance = None
   ...:     def __new__(class_, *args, **kwargs):
   ...:         if not isinstance(class_._instance, class_):
   ...:             class_._instance = object.__new__(class_)
   ...:         return class_._instance
   ...:

In [2]: class Test(Singleton):
   ...:     def __init__(self, name=None):
   ...:         print(name)
   ...:
   ...: test1 = Test('a')
a

请注意,每次“实例化”您的单例时都会调用 __init__

In [3]: test2 = Test('b')
b

In [4]: test1 is test2
Out[4]: True

这可能是可取的,也可能不是。

但是如果你需要一个单例,请认真重新考虑 classes。即使在它们有意义的语言中,例如Java,它们通常是 anti-pattern,并且只是一种在 OOP-encapsulated 外观中隐藏可变全局状态的方法。这又让我想起了最初的建议,那就是只使用一个模块,那么你就没有伪装了。