Skip to content

Instantly share code, notes, and snippets.

@saghul
Created March 7, 2011 22:22
Show Gist options
  • Save saghul/859400 to your computer and use it in GitHub Desktop.
Save saghul/859400 to your computer and use it in GitHub Desktop.
WeakSingleton
# Derived from Singleton class by Dan Pascu on python-application package
from new import instancemethod
from weakref import WeakValueDictionary
from application.python.decorator import preserve_signature
class WeakSingleton(type):
"""
Metaclass for making singletons. Instances are kep in a weak-value
dictionary, so they will vanish if only the WeakSingleton is holding
them.
"""
def __init__(cls, name, bases, dic):
from types import UnboundMethodType
if type(cls.__init__) is UnboundMethodType:
initializer = cls.__init__
elif type(cls.__new__) is UnboundMethodType:
initializer = cls.__new__
else:
def initializer(self, *args, **kw): pass
@preserve_signature(initializer)
def instance_creator(cls, *args, **kwargs):
key = (args, tuple(sorted(kwargs.iteritems())))
try:
hash(key)
except TypeError:
raise TypeError("cannot have singletons for classes with unhashable arguments")
if key not in cls._instances:
obj = super(WeakSingleton, cls).__call__(*args, **kwargs)
cls._instances[key] = obj
return cls._instances[key]
super(WeakSingleton, cls).__init__(name, bases, dic)
cls._instances = WeakValueDictionary()
cls._instance_creator = instancemethod(instance_creator, cls, type(cls))
def __call__(cls, *args, **kw):
return cls._instance_creator(*args, **kw)
# Test
if __name__ == '__main__':
class Foo(object):
__metaclass__ = WeakSingleton
f = Foo()
print id(f)
g = Foo()
print id(g)
print Foo._instances.items()
del f
print Foo._instances.items()
del g
print Foo._instances.items()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment