patron python singleton properties

patron - Python: @staticmethod con @property



patron singleton python (4)

yo quiero

Stats.singleton.twitter_count += 1

y pensé que podría hacer

class Stats: singleton_object = None @property @staticmethod def singleton(): if Stats.singleton_object: return Stats.singleton_object Stats.singleton_object = Stats() return Stats.singleton()

Pero arroja una excepción:

>>> Stats.singleton.a = "b" Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: ''property'' object has only read-only attributes (assign to .a)


El usuario kaizer.se estaba en algo en cuanto a la pregunta original. Avancé un poco más en términos de simplicidad, por lo que ahora solo se necesita un único decorador:

class classproperty(property): def __get__(self, cls, owner): return classmethod(self.fget).__get__(None, owner)()

Uso:

class Stats: _current_instance = None @classproperty def singleton(cls): if cls._current_instance is None: cls._current_instance = Stats() return cls._current_instance

Como se señaló, esta forma de crear un singleton no es un buen patrón de diseño; si eso debe hacerse, una fábrica de metaclass es una forma mucho mejor de hacerlo. Sin embargo, estaba entusiasmado con la perspectiva de una propiedad de clase, así que ahí está.


Los métodos estáticos no tienen sentido en Python. Eso es porque no hacen nada que los métodos de clase no puedan hacer, y son métodos de clase mucho más fáciles de extender en el futuro (cuando los métodos de clase múltiple se usan entre sí, etc.).

Lo que necesita es simplemente una propiedad de método de clase.

Tengo una propiedad de método de clase de mi código aquí. Solo es de solo lectura, eso era todo lo que necesitaba (entonces el resto es un ejercicio para el lector):

class ClassProperty (property): """Subclass property to make classmethod properties possible""" def __get__(self, cls, owner): return self.fget.__get__(None, owner)() # how I would use it class Stats: singleton_object = None @ClassProperty @classmethod def singleton(cls): if cls.singleton_object is None: cls.singleton_object = cls() return cls.singleton_object


Los singletons no tienen sentido en Python.

class A: class_var = object() # two objects a, b = A(), A() # same var everywhere assert a.class_var is b.class_var is A.class_var

Los int s de Python son diferentes de los simples object s, por lo que no siempre es tan simple. Pero para tus propósitos, esto parece ser suficiente:

class Stats: twitter_count = 0 Stats.twitter_count +=1 Stats.twitter_count +=1 assert Stats.twitter_count == 2


Siguiendo con lo que KyleAlanHale escribió:

Su ejemplo funciona muy bien, hasta que intentes y hagas:

Stats.singleton = 5

Esto no le dará un error, sobrescribirá la función, de modo que cuando escriba a continuación

single = Stats.singleton print single

Obtendrás

5

Creo que es mejor que uses la respuesta de Kyle sin la decoración @classproperties.