[#development #snippet] Singleton in Python

Ciao,

pubblico uno snippet che avevo prodotto per il mio progetto di tesi, che può tornare utile a chiunque, per implementare il pattern singleton in Python.

from __future__ import absolute_import
from functools import wraps
__author__ = 'Patrizio Tufarolo'

class SingletonException(Exception):
    pass

class Singleton(object):
    _instances = {}
    _configured = False
    def __new__(class_, *args, **kwargs):
        if class_ not in class_._instances:
            class_._instances[class_] = super(Singleton, class_).__new__(class_, *args, **kwargs)
        return class_._instances[class_]

    def configure(self):
        self._configured = True

    def check_configured(self):
        return self._configured

    @staticmethod
    def _if_configured(this_exception):
        if not this_exception or not issubclass(this_exception, SingletonException):
            this_exception = SingletonException

        def _configured_decorator(func):
            @wraps(func)
            def wrapper(inst, *args, **kwargs):
                if not inst.check_configured():
                    raise this_exception("Object not configured properly")
                else:
                    return func(inst, *args, **kwargs)

            return wrapper

        return _configured_decorator

L’implementazione fornita contiene però una peculiarità:
la mia necessità era quella di poter istanziare delle classi Singleton per lanciare delle routine di configurazione prima di poter effettivamente utilizzare un oggetto.
Alcuni metodi della mia classe Singleton, pertanto, devono poter essere eseguiti solo dopo la configurazione dell’oggetto.
L’espediente da me utilizzato per risolvere il problema è piuttosto banale: ho utilizzato un flag booleano (_configured), inizialmente settato a False.
Il metodo check_configure ne restituisce il valore, e il metodo configure lo imposta a True.
Per dichiarare poi i metodi eseguibili solo ad oggetti configurati utilizzo poi il decoratore _if_configured, la quale, nel caso l’oggetto non sia ancora stato configurato, solleva un’eccezione (anche personalizzabile, se la classe viene passata come parametro).

Per utilizzare il mio codice è sufficiente far ereditare la propria classe dalla classe Singleton da me fornita:

class CustomException(Exception):
    pass

class MioOggettoSingleton(Singleton):
    def __init__(self):
        '''do something cool'''
        Singleton.__init__(self)

    def configure(self):
        Singleton.configure(self)

    @Singleton._if_configured
    def metodo_eseguibile_solo_se_configurato(self):
        print("Ok oggetto configurato")

    def metodo_eseguibile_sempre(self):
        print("Vabbe io funziono sempre")

    @Singleton._if_configured(CustomException)
    def metodo_eseguibile_solo_se_configurato(self):
        print("Ok oggetto configurato")
        '''se non fosse configurato ritornerebbe un'eccezione'''

Spero vi sia utile!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*