Creating classes and objects more than once?

Viktor Kerkez alefnula at gmail.com
Thu Nov 27 23:28:13 CET 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