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 外观中隐藏可变全局状态的方法。这又让我想起了最初的建议,那就是只使用一个模块,那么你就没有伪装了。
我想制作一个 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 外观中隐藏可变全局状态的方法。这又让我想起了最初的建议,那就是只使用一个模块,那么你就没有伪装了。