[pyar] Singleton and Factory Patterns.

Joaquin Duo joaduo en gmail.com
Mie Dic 17 04:33:16 ART 2014


Hay muchas formas de hacer un de singleton.
Tal vez tu pregunta se debe a que encontraste demasiados alternativas?
http://python-3-patterns-idioms-test.readthedocs.org/en/latest/Singleton.html

Hasta podés hacerlo "a lo java" con un método estático/o de la clase.

A mi me gusta utilizar la solución del decorator, ejemplo:
https://github.com/joaduo/smoothtest/blob/master/smoothtest/autotest/Context.py#L12

Lo bueno es que el decorator no te cambia en nada el código de la clase (no
intrusivo) y la transforma en singleton.
Otra ventaja es que los IDEs te devuelven la interface de la clase original
al autocompletar. (un gran plus!) (te recomiendo Pydev o Liclipse como IDE)
Lo malo es que como la clase es decorada, no podés heredar fácilmente de la
clase (se puede resolver, pero la solución que puse no lo resuelve)

Es fácil de darse cuenta por qué no se puede heredar si entendés los
decorators en python.

Hacer:
@singleton_decorator
class Foo(object):
    pass

es lo mismo que hacer
class Foo(object):
    pass

Foo = singleton_decorator(Foo)

Se ves bien, ahora Foo pasa a ser una instancia de singleton_decorator, que
siempre te va a devolver la misma instancia de Foo al invocar __call__.
Como es una instancia de singleton_decorator no podés heredar de ésta.
Se puede hacer que la instancia implemente la API necesaria para hacerse
pasar por Foo a la hora de heredar de ésta, pero como dije la solución que
puse no lo hace.

Otra desventaja es que la clase original queda "escondida" dentro de la
instancia de singleton_decorator y, por ejemplo, aplicar un monkey patch
sería más difícl. (aunque en general los monkey patchs no son muy
recomendables)

Lógicamente las demás implementaciones también tendrán sus pro y contra.
(no me he tomado el tiempo de analizarlas a cada una)

Saludos!

2014-12-13 15:32 GMT-03:00 Javier Marcon <javiermarcon en gmail.com>:
>
> El 13/12/14 a las 15:16, Roberto Alsina escibió:
> > On 13/12/14 12:47, Javier Marcon wrote:
> >> El 12/12/14 a las 19:35, Facundo Batista escibió:
> >>> 2014-12-12 15:59 GMT-03:00 Roberto Alsina <ralsina en netmanagers.com.ar
> >:
> >>>
> >>>> En python hay un objeto singleton: el módulo.
> >>>>
> >>>> Si haces un modulo como este, siempre vas a tener una sola conexion:
> >>>>
> >>>>
> >>>> __conexion = None
> >>>>
> >>>> def conectate():
> >>>>      __conexion = foo.bar.base()
> >>>>
> >>>> def conexcion():
> >>>>      return __conexion
> >>> Aunque la idea de usar el módulo como singleton está buena, este
> >>> código no funciona, porque la asignación adentro de conectate te crea
> >>> un nombre local, nada que ver con el global.
> >>>
> >>> Algo como esto sí funcionaría:
> >>>
> >>> """
> >>> conexion = None
> >>>
> >>> def conectate():
> >>>      global conexion
> >>>      conexion = foo.bar.base()
> >>> """
> >>>
> >>> Simple y sucio. Se pueden hacer cosas más limpias y complejas, sin
> >>> embargo, pero muchas veces con esto alcanza.
> >>>
> >>> Slds.
> >>>
> >> Yo lo haría asi:
> >>
> >> class database:
> >>      conexion = None
> >>
> >>     def __init__(self):
> >>          if not self.__class__.conexion:
> >>              self.start()
> >>          return self.__class__.conexion
> >>
> >>      def start(self):
> >>          self.__class__.conexion = Database().connect()
> >>
> >> Salu2,
> >>
> >> Javier.
> >
> > Fijate como queda del lado del que lo usas:
> >
> > import cosa
> > conn = cosa.database().conexion
> >
> > La que usa el modulo como singleton queda
> >
> > import cosa
> > conn = cosa.conexion()
> >
> > Me parece mas linda la segunda.
> Me mezcle con los nombres, en realidad queria hacer algo asi:
>
> database.py:
>
> import sqlite3
>
> class Database:
>
>     conexion = None
>
>     def __init__(self):
>          if not self.__class__.conexion:
>              self.start()
>          return self.__class__.conexion
>
>      def start(self):
>          self.__class__.conexion = sqlite3.connect("db.sqlite")
>
>
> run.py:
>
> from database import Database
>
> conexion = Database()
> cursor = conexion.cursor()
> sql = "select * from clientes"
> cursor.execute(sql)
> cliente = cursor.fetchone()
> ...
>
> _______________________________________________
> pyar mailing list pyar en python.org.ar
> http://listas.python.org.ar/listinfo/pyar
>
> PyAr - Python Argentina - Sitio web: http://www.python.org.ar/
>
> La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de
> Argentina - http://www.usla.org.ar
>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.python.org.ar/pipermail/pyar/attachments/20141217/614a10a3/attachment.html>


More information about the pyar mailing list