Anda di halaman 1dari 2

E como fica o Singleton no Python?

Publicado em 14/04/2014 por Diego Garcia


Ultimamente tenho passado a dar mais ateno ao Python e tenho gostado muito da experincia.
Obviamente que, para qualquer desenvolvedor, a transio de uma linguagem para outra pode
ocasionar alguns choques. Vejo isso como algo positivo, simplesmente por que, voc no pode
codificar em um linguagem como codificaria em outra. Em outras palavras, voc no pode
desenvolver em python da mesma forma que desenvolve em delphi. Desenvolver desta forma um
erro muito comum e que pode atrapalhar bastante no processo de aprendizado.
O mais recente choque desses que tive foi com relao ao pattern Sigleton (GoF). Isso porque,
aparentemente em python existe outro pattern semelhante, que na prtica funciona da mesma
maneira, o pattern Borg.
Se no pattern Singleton, garantimos somente uma instancia de um determinado objeto, no Borg
podemos ter N instancias do mesmo objeto, porm, todas essas instancias compartilham o mesmo
estado. O que isso significa? Significa que, em um objeto de uma classe Borg, se voc atribuir
10 para o atributo x, voc est alterando o estado de todos os objetos instanciados dessa classe.
Para descomplicar, vamos ver os dois padres na prtica, comeando pelo Borg:
class Borg:
__shared_state = {}

@property
def x(self):
return self.__x

@x.setter
def x(self, value):
self.__x = value

def __init__(self):
self.__dict__ = self.__shared_state

O atributo __shared_state um atributo de classe e o Self.__dict__ consiste em uma estrutura


interna do Python que armazena o estado do objeto. Em uma forma simplista de dizer, o cdigo
acima faz com que a cada nova instancia da classe Borg (__init__), o estado do objeto passe a ser
controlado pelo atributo __shared_state.
J o Singleton no possui nenhuma novidade, a inteligncia toda fica por conta do mtodo
instance().
class Singleton:
__instance = None

@property
def x(self):
return self.__x

@x.setter
def x(self, value):
self.__x = value
@staticmethod
def instance():
if not Singleton.__instance:
Singleton.__instance = Singleton()
return Singleton.__instance

Em termos de uso, como mencionei no comeo do post, no temos muitas diferenas, veja um
exemplo:
s1 = Singleton.instance()
s2 = Singleton.instance()
s1.x = 10

b1 = Borg()
b2 = Borg()
b1.x = 20

print('Singleton')
print('s1.x={} | s2.x={}'.format(s1.x, s2.x))
print('id(s1)={} | id(s2)={}'.format(id(s1), id(s2)))
print('-------------------')
print('Borg')
print('b1.x={} | b2.x={}'.format(b1.x, b2.x))
print('id(b1)={} | id(b2)={}'.format(id(b1), id(b2)))

A sada do cdigo acima ser a seguinte:


Singleton
s1.x=10 | s2.x=10
id(s1)=30928456 | id(s2)=30928456
-------------------
Borg
b1.x=20 | b2.x=20
id(b1)=30928512 | id(b2)=30928624

Veja que nos objetos Borg, o id retornado diferente, o que significa que estamos lidando com
instancias distintas, porm, o valor do atributo X o mesmo para as duas instancias.
Uma vantagem do Borg que o seu funcionamento se estende para as suas subclasses, porm, as
vezes o que realmente queremos somente uma instancia de uma determinada classe.
Independente de qual o melhor, conhecer os dois e estar pronto para us-los ou interpret-los no
momento certo com certeza a melhor opo.