When to use a Singleton in python?

不羁的心 提交于 2019-12-12 10:43:51

问题


There are many questions related to the use of the Singleton pattern in python, and although this question might repeat many of the aspects already discussed, I have not found the answer to the following specific question.

Let's assume I have a class MyClass which I want to instantiate only exactly once. In python I can do this as follows in the code myclass.py:

class MyClass(object): 
    def foo(self):
        ....


instance = MyClass()

Then in any other program I can refer to the instance simply with

import myclass
myclass.instance.foo()

Under what circumstances is this approach enough? Under what circumstances is the use of a Singleton pattern useful/mandatory?


回答1:


The singleton pattern is more often a matter of convenience than of requirement. Python is a little bit different than other languages in that it is fairly easy to mock out singletons in testing (just clobber the global variable!) by comparison to other languages, but it is neverthess a good idea to ask yourself when creating a singleton: am I doing this for the sake of convenience or because it is stricly necessary that there is only one instance? Is it possible that there may be more than one in the future?

If you create a class that really will be only constructed once, it may make more sense to make the state a part of the module, and to make its methods into module-level functions. If there is a possibility that the assumption of exactly one instance may change in the future, then it is often much better to pass the singleton instance around rather than referencing the singleton through a global name.

For example, you can just as easily implement a "singleton" this way:

if __name__ == '__main__':
   instance = MyClass()
   doSomethingWith(instance)

In the above, "instance" is singleton by virtue of the fact that it is constructed only once, but the code that handles it is provided the instance rather than referencing module.instance, which makes it easier to reuse pieces of the code if, in some future situation, you need more than one MyClass.




回答2:


Assuming you want to use a module as a singleton as Michael Aaron Safyan suggests, you can make it work even if the module isn't imported by the main code by doing something like the following (in the main code or a module it does import direct or indirectly). What it does is make aninstanceclass attribute initialized it to one, and then replaces the module object insys.moduleswith the instance created:

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

I've found singletons a useful way to implement "registers" of things when it makes sense to have only one (registry) -- such as a group of classes for a class factory, a group of constants, or a bundle of configuration information. In many cases just a regular Python module will do fine because, by default, they're effectively already singletons due to fact that those already loaded get cached in the sys.modulesdictionary.

Occasionally however, class instances are preferable because they can be passed construction parameters and have properties -- something built-in module objects don't and can't be made to possess. Limitations like that can be worked-around using the trick shown above which effectively turns custom class instances into module objects.

The idea of using class instances as module objects is from Alex Martelli's ActiveState recipe named Constants in Python.




回答3:


In my humble opinion, there are two sides to the singleton pattern.

  • you want a single context for a given service because more than one does not make sense.
  • you want to absolutely prevent people from creating two object of a given type because it might break your service

While the first case may have some applications (logging service), the second one is often the sign of a bad design.

You should design your API so that your users should not have to think about this problem. But if they dig through your undocumented layers to find your hidden constructor and want to use it for whatever reason, they should not have to deal with useless constructs created to prevent them to do what they need to do.



来源:https://stackoverflow.com/questions/14600075/when-to-use-a-singleton-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!