Python: Singleton

Palavras-chave: Python, Design Patterns, Padrões de Projeto, OOP, POO

Um Singleton é um dos padrões de projeto descrito no famoso livro “Design Patterns” escrito pela GoF (Gang of Four) e o seu funcionamento é bastante simples: uma classe é chamada de Singleton quando ela permite apenas uma única instância.

A maneira de se implementar um Singleton descrita no livro consiste em definir um método get_instance() na classe que ficará responsável por criar a primeira instância e a partir daí retorná-la sempre que for chamada.

Mas a natureza dinâmica de Python e seu sistema de meta-classes permitem que se crie uma classe chamada Singleton genérica que podemos usar como super-classe dos nossos próprios Singletons:

class Singleton(object):
   def __new__(cls, *args, **kwargs):
      if '_inst' not in vars(cls):
         cls._inst = type.__new__(cls, *args, **kwargs)
      return cls._inst

Agora, para que a sua classe se transforme em Singleton basta apenas derivá-la desta classe e não é mais necessário implementar o método get_instance(). O seu uso ficaria assim:

class MeuSingleton(Singleton):
   pass

a = MeuSingleton()
b = MeuSingleton()

print a is b # imprimirá True, pois trata-se da mesma instância

Essa dica faz parte do livro Python Cookbook e foi escrita por Jürgen Hermann. No livro você poderá encontrar as explicações detalhadas sobre essa classe e mais uma série de outras dicas interessantes sobre diversos assuntos.

This entry was posted in Python. Bookmark the permalink.

6 Responses to Python: Singleton

  1. Walter Cruz says:

    Oi Osvaldo! Parece que há um pequenino erro no código!
    Deve ser:
    cls._inst = object.__new__(cls, *args, **kwargs)
    ao invés de:
    cls._inst = type.__new__(cls, *args, **kwargs)

  2. yguaratã says:

    Uma outra maneira de se criar singletons em Python é instaciar as classes(que serão singletons) em um módulo separado. Sempre que se precisar das mesmas é só importar o módulo. Como os módulos são compilados apenas uma vez, quando importados, então temos nassas singletons.

  3. yguaratã,

    O que faz o seu exemplo funcionar não é o fato do módulo ser __compilado__ apenas uma vez e sim que ele só é __lido/executado__ uma vez, sendo ele mesmo um singleton.

  4. yguaratã says:

    É o que meu comentário diz: “…quando importados…”

  5. Bruno Tikami says:

    Olá Osvaldo,

    tomei a liberdade de usar este código que você postou na minha aplicação e hoje me deparei com uma situação interessante:

    quando crio uma nova instância, a parte do método __new___ funciona normalmente mas ainda assim o método __init__ da classe é chamado… É possível evitar isso ?

    Obrigado,

    Tkm

  6. Ademar Reis says:

    O melhor exemplo de implementação de singleton que eu encontrei foi no texto sobre meta-classes do GVR: http://www.python.org/download/releases/2.2.3/descrintro/

    Não sei se vai ficar direito no comentário aqui do wordpress, mas aí vai a minha implementação com base no exemplo do texto:

    class Singleton(object):
    def __new__(cls, *args, **kwds):
    it = cls.__dict__.get(“__it__”)
    if it is not None:
    return it
    cls.__it__ = it = object.__new__(cls)
    it.__1st_init__(*args, **kwds)
    return it
    def __1st_init__(self, *args, **kwds):
    pass

    class FoobarTon(Singleton):
    def __1st_init__(self):
    print “calling __1st_init__”
    self.x = 0
    def __init__(self):
    print “calling __init__”
    def inc(self):
    self.x += 1

    print “FoobarTon”
    f1 = FoobarTon()
    f2 = FoobarTon()
    f3 = FoobarTon()
    f1.inc();
    f2.inc();
    f3.inc();

    print “f1 is fs2: %s” % str(f1 is f2)
    print “f1 is fs3: %s” % str(f1 is f3)
    print “f3.x: %d” % f3.x

    Anyway, esse código tá no meu junk-code: http://svn.ademar.org/code/trunk/junk-code/ (é o último exemplo do singleton_vs_borg.py).

Comments are closed.