开发者

Python singleton pattern

someone can tell me why this is incorrect as a singleton pattern:

class preSingleton(object):
    def __call__(self):
        return self

singleton = preSingleton()

# singleton is actually the singleton

a = singleton()
b = singleton()

print a==b  

a.var_in_a = 100
b.var_in_b = 'hello'

print a.var_in_b
print b.var_in_a

Edit: The above code prints:

True
hello
100

thank you very much

Part Two

Maybe this is better?

class Singleton(object):
    def __new__(cls):
        return cls

a = Singleton()
b = Singleton()

print a == b

a.var_in_a = 100
b.var_in_b = 'hello'

print a.var_in_b
print b.var_in_a

Edit: The above code prints:

True
hel开发者_JS百科lo
100

Thanks again.


Singletons are actually really simple to make in Python. The trick is to have the module do your encapsulation for you and not make a class.

  • The module will only be initialized once
  • The module will not be initialized until the first time it is imported
  • Any attempts to re-import the module will return a pointer to the existing import

And if you want to pretend that the module is an instance of a class, you can do the following

import some_module
class SomeClass(object):
    def __init__(self):
        self.singleton = some_module


Because this is not a singleton. Singleton must be single, your object is not.

>>> class preSingleton(object):
...     def __call__(self):
...         return self
...
>>> singleton = preSingleton()
>>> singleton2 = preSingleton()
>>> singleton
<__main__.preSingleton object at 0x00C6D410>
>>> singleton2
<__main__.preSingleton object at 0x00C6D290>


This is actualy the Borg pattern. Multiple objects that share state.

That's not to say there's anything wrong with it, and for most if not all use cases it's functionaly equivalent to a singleton, but since you asked...

edit: Of course since they're Borg objects, each instance uses up more memory so if you're creating tons of them this will make a difference to resource usage.


Here's a sexy little singleton implemented as a decorator:

def singleton(cls):
    """Decorate a class with @singleton when There Can Be Only One."""
    instance = cls()
    instance.__call__ = lambda: instance
    return instance

Use it like this:

@singleton
class MySingleton:
    def spam(self):
        print id(self)

What happens is that outside of the class definition, MySingleton will actually refer to the one and only instance of the class that exists, and you'll be left with no mechanism for creating any new instances. Calling MySingleton() will simply return the exact same instance. For example:

>>> MySingleton
<__main__.MySingleton instance at 0x7f474b9265a8>
>>> MySingleton()
<__main__.MySingleton instance at 0x7f474b9265a8>
>>> MySingleton() is MySingleton
True
>>> MySingleton.spam()
139944187291048
>>> MySingleton().spam()
139944187291048


I don't see the problem (if it walks like a duck and quacks like a duck...). Looks like a singleton to me.

It works differently from a Java singleton (for example) because Python uses the same syntax to call a function as to create a new instance of an object. So singleton() is actually calling the singleton object, which returns itself.


You can do this with your class:

>>> class preSingleton(object):
...     def __call__(self):
...         return self
...
>>> x = preSingleton()
>>> y = preSingleton()
>>> x == y
False

So, more than one instances of the class can be created and it violates the Singleton pattern.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜