在python中使用Singleton模式有很多问题,尽管这个问题可能会重复已经讨论过的许多方面,但我还没有找到以下具体问题的答案。
假设我有一个类MyClass
,我只想实例化一次。在python中,我可以在代码myclass.py
中执行以下操作:
class MyClass(object):
def foo(self):
....
instance = MyClass()
然后在任何其他程序中,我只需使用
即可引用该实例import myclass
myclass.instance.foo()
这种方法在什么情况下足够?在什么情况下使用Singleton模式有用/强制?
答案 0 :(得分:7)
单身模式通常是方便而非要求。 Python与其他语言略有不同,因为与其他语言相比,在测试中模拟单例非常容易(只是破坏了全局变量!),但在创建单例时要问自己是个好主意:我这样做是为了方便还是因为只有一个实例是非常必要的?未来可能会有不止一个吗?
如果创建一个实际上只构造一次的类,那么将状态作为模块的一部分并将其方法转换为模块级函数可能更有意义。如果将来某个实例的假设有可能发生变化,那么通过单例实例通常要好得多,而不是通过全局名称引用单例。
例如,您可以通过这种方式轻松实现“单身”:
if __name__ == '__main__':
instance = MyClass()
doSomethingWith(instance)
在上面,“实例”是单例,因为它只构造了一次,但处理它的代码是提供实例而不是引用module.instance
,这使得重用件更容易如果在某种情况下,您需要多个MyClass
。
答案 1 :(得分:3)
假设您希望将模块用作单身人士,正如Michael Aaron Safyan建议的那样,即使主要代码没有通过执行以下操作(在主代码或模块中)导入模块,也可以使其工作它直接或间接导入)。它的作用是使instance
类属性初始化为1,然后用创建的实例替换sys.modules
中的模块对象:
class _MyClass(object):
def foo(self):
print 'foo()'
_MyClass.instance = _MyClass()
import sys
_ref = sys.modules[__name__] # Reference to current module so it's not deleted
sys.modules[__name__] = _MyClass.instance
我发现单例是实现“寄存器”的有用方法,只有一个(注册表)才有意义 - 例如类工厂的一组类,一组常量或一个包配置信息。在许多情况下,只需一个常规的Python模块就可以了,因为默认情况下,它们实际上已经是单例,因为已经加载的那些被缓存在sys.modules
字典中。
然而,有时候,类实例更可取,因为它们可以传递构造参数并且具有properties - 内置模块对象不能并且不能被拥有。这样的限制可以使用上面显示的技巧进行解决,这有效地将自定义类实例转换为模块对象。
将类实例用作模块对象的想法来自Alex Martelli ActiveState名为Constants in Python的食谱。
答案 2 :(得分:1)
在我的拙见中,单身人士模式有两个方面。
虽然第一种情况可能有一些应用程序(日志记录服务),但第二种情况通常是设计不良的标志。
您应该设计API,以便用户不必考虑此问题。但是如果他们挖掘你未记录的层来找到你隐藏的构造函数并且想要出于任何原因使用它,那么它们就不应该处理无用的构造来阻止它们做他们需要做的事情。