But this means that there is no way to create a safe Singleton in
python, because the classes are also created twice.
This is the problem that I encountered. I created a complex
implementation of a Singleton pattern using metaclasses because I
needed the __init__ method to be called just once and I wanted to use
inheritance from the Singleton class. Here is the code:
class SingletonMetaclass(type):
'''Singleton Metaclass
This metaclass is used for creating singletons.
It changes the class __new__ method to maintain only one instance
of the
class, and tweaks the __init__ method to be executed only once
(when the
first instance of the class is created.
Usage:
... """Real singleton class.
...
... You have to set the __metaclass__ attribute to
SingletonMetaclass,
... and define the __init__ function. Everythin else will be
done by
... metaclass.
... """
... __metaclass__ = SingletonMetaclass
... def __init__(self, data):
... print 'Initializing'
... self.data = data
...
actually happen
Initializing
'First initialization'
'First initialization'
'''
def __new__(cls, name, bases, dct):
dct['__new__'] = SingletonMetaclass._dekorate_new()
dct['get_instance'] = SingletonMetaclass._decorate_get_instance
()
try:
dct['__init__'] = SingletonMetaclass._dekorate_init(dct
['__init__'])
except KeyError:
init_functions = [getattr(base, '__init__') for base in
bases if hasattr(base, '__init__')]
if init_functions:
dct['__init__'] = SingletonMetaclass._dekorate_init
(init_functions[0])
else:
raise Exception('Don\'t use SingletonMetaclass, use
inheritance from Singleton class!')
return type.__new__(cls, name, bases, dct)
@staticmethod
def _dekorate_init(function):
def wrapper(self, *args, **kwargs):
if not hasattr(self, '_singleton_initialized'):
function(self, *args, **kwargs)
setattr(self, '_singleton_initialized', True)
return wrapper
@staticmethod
def _dekorate_new():
def wrapper(cls, *p, **k):
if not hasattr(cls, '_instance'):
cls._instance = object.__new__(cls)
return cls._instance
return wrapper
@staticmethod
def _decorate_get_instance():
@classmethod
def wrapper(cls):
if not hasattr(cls, '_instance'):
return None
return cls._instance
return wrapper
class Singleton(object):
'''Singleton class
Inherit from this class if you want to have a singleton class.
Never use SingletonMetaclass!
Usage:
... """Singleton without __init__ method"""
... pass
...
... """Singleton with __init__ method"""
... def __init__(self, data):
... print 'Initializing'
... self.data = data
...
actually happen
Initializing
'First initialization'
'''
__metaclass__ = SingletonMetaclass
def __init__(self):
pass
if __name__ == '__main__':
import doctest
doctest.testmod()
The problem started when the class gets imported in two different
ways, and the class gets created twice!??!
Do You have any suggestions how to solve this problem.