3

Normally, I would expect a function variable to be lost after execution of that function. In the below case where I wrote a Singleton following some tutorials, it works, though. One could argue that instancesshould be empty again everytime the singleton function is called.

def singleton(cls):
    instances = {}
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance

@singleton
class cls(object):
    pass

My assumption is that indeed instances would be lost if it weren't the case that a dynamic function get_instanceis returned in which a reference to the variable is stored so that it is still available. This leads to the fact that instances continues existing.

Is that interpretation correct? Is it also correct that for every get_instance call there is a separate "instance" of instances? They cannot be the same as for every singleton call there is a fresh instances = {}.

Xiphias
  • 4,468
  • 4
  • 28
  • 51

1 Answers1

1

This:

>>> @singleton
>>> class cls(object):
...    pass

Is equivalent to this:

>>> class cls(object):
...    pass
>>> cls = singleton( cls )

singleton is run only once per class you decorate it with (not per instantiation). The function it returns, which is a different instance of get_instance for every time singleton is called, is run once per instantiation. Thus only one instances object is created even when you attempt to instantiate many cls objects.

Note what sort of callable cls actually is after the above:

>>> cls
<function get_instance at 0x0000000002352B38>

The instances objects are not reclaimed until it they are no longer reachable because Python uses garbage collection. It is considered reachable as long as the function get_instance, which closes over it, is reachable.

svk
  • 5,854
  • 17
  • 22
  • Okay, my assumption probably wasn't explained 100% clearly. Per "singletoned" class there is one `instances` *each*. That's what I thought. Yes, there is only one `instances` per class, no matter how often you instantiate it. Would you agree with me? – Xiphias Nov 29 '13 at 08:53
  • @Tobias Yes, that's right. That object is still reachable through a closure, so it's not being reclaimed. – svk Nov 29 '13 at 08:55