views:

172

answers:

5

Hi,

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
hello
100

Thanks again.

+2  A: 

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>
unbeli
The `PreSingleton` isn't the singleton, the `singleton` is. You're misunderstanding the code.
Skilldrick
no I didn't misunderstand. Neither are singletons. If you run the code like that twice, you will get different instances, period.
unbeli
@Skilldrick `singleton` is an instance of `preSingleton`. It is not a class and hence cannot be said to follow Singleton pattern. Otherwise in that sense, every instance of a class is a singleton in itself.
abhin4v
I know, but when you 'call' `singleton`, it returns an object. If `singleton` were a class, and you 'called' it, it would return an object. To all intents and purposes, `singleton` is acting as a singleton.
Skilldrick
Ok, then any variable is a singleton. You just get a value and it's always the same, whoa, singleton!
unbeli
If you imagine that `singleton` is a class, then every time you instantiate it you get the same object. To me that fulfills the meaning of a singleton. Just because it isn't implemented with a private constructor and static methods and all that jazz, doesn't mean it's any less valid as an implementation.
Skilldrick
@Skilldrick I can only partially agree. In it's current shape one can only *pretend* it's a singleton. If you clean the namespace (remove/overwrite the preSingleton), then it might become a real singleton, which does not invite creation of more of a kind.
unbeli
+1  A: 

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.

Skilldrick
A: 

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.

abhin4v
`preSingleton` isn't the singleton, `singleton` is.
Skilldrick
+1  A: 

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.

Simon Hibbs
+3  A: 

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
unholysampler