Creating classes and objects more than once?
Viktor Kerkez
alefnula at gmail.com
Thu Nov 27 17:28:13 EST 2008
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:
>>> class MySingleton(object):
... """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
...
>>> first = MySingleton('First initialization') # Only this
actually happen
Initializing
>>> second = MySingleton('Second initialization') # This won't
happen
>>> first.data
'First initialization'
>>> second.data
'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:
>>> class EmptySingleton(Singleton):
... """Singleton without __init__ method"""
... pass
...
>>> first = EmptySingleton()
>>> second = EmptySingleton()
>>> assert id(first) == id(second)
>>>
>>> class InitSingleton(Singleton):
... """Singleton with __init__ method"""
... def __init__(self, data):
... print 'Initializing'
... self.data = data
...
>>> first = InitSingleton('First initialization') # Only this
actually happen
Initializing
>>> second = InitSingleton('Second initialization') # This won't
happen
>>> first.data
'First initialization'
>>> assert first.data == second.data
>>>
'''
__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.
More information about the Python-list
mailing list