Python: @staticmethod con @property

quiero

Stats.singleton.twitter_count += 1 

y pensé que podí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 lanza una excepción:

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

Singletons son inútiles 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 de Python son diferentes de los object simples, por lo que no siempre es así de 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 

El usuario kaizer.se estaba en algo en cuanto a la pregunta original. Lo llevé un paso más allá en términos de simplicidad, de modo que ahora solo se requiere 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 metaclases 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. Esto se debe a que no hacen nada que los métodos de clase no puedan, y son métodos de clase mucho más fáciles de extender en el futuro (cuando varios métodos de clase se usan entre sí, etc.).

Lo que necesitas 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 (por lo que el rest 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 

Siguiendo con lo que KyleAlanHale escribió:

Su ejemplo funciona muy bien, hasta que lo intentas y haces:

 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 usar la respuesta de Kyle sin la decoración de @classproperties.