2009-11-08 17 views
29

voglioPython: @staticmethod con @property

Stats.singleton.twitter_count += 1 

e ho pensato che avrei potuto fare

class Stats: 
    singleton_object = None 

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

Ma viene generata un'eccezione:

>>> 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) 
+2

dove è definito 'singleton_object'? – tonfa

+3

dove è definito 'self'? – tonfa

+2

define "not working" – u0b34a0f6ae

risposta

8

Singletons sono inutili in 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 

di Python int s sono differente da semplici object s, quindi non è sempre così semplice. Ma per i tuoi scopi, questo sembra essere abbastanza:

class Stats: 
    twitter_count = 0 

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

Ho un po 'di backstory, nel senso che voglio un db AppEngine.L'oggetto Model deve essere un singleton (solo un oggetto Stats nel database). Quindi ho bisogno di avere almeno un'istanza in memoria. –

+1

Non capisco. Quando hai un DB dietro, tutte le istanze condividono già lo stesso stato, lo stato di una riga nel tuo DB. Due istanze potrebbero non essere identiche, ma qualsiasi ORM che merita quel nome farà in modo che la modifica cambierà anche l'altra. –

+32

Ovunque sentite dire che i metodi statici e i singleton sono inutili in Python, yadda, yadda. Questa è una merda. Singleton è un modello valido e necessario. Cosa "noi" vogliamo che la più ampia comunità di programmazione sappia è "come" dovremmo farlo nel modo giusto. Qualsiasi risposta che non risponda direttamente è, penso, inutile. Io, per esempio, sono perplesso su questo problema. :-) Aiuto! – 010110110101

6

metodi statici non lo fanno ha senso in Python. Questo perché non fanno nulla che i metodi di classe non possano fare, e sono metodi di classe molto più facili da estendere in futuro (quando i metodi di classi multiple si usano l'un l'altro ecc.).

Quello che ti serve è semplicemente una proprietà del metodo di classe.

Ho una proprietà del metodo di classe dal mio codice qui. E 'solo di sola lettura, che era tutto il necessario (in modo che il resto è un esercizio per il lettore):

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 
+3

Non penso che ci sia una risposta al tuo "esercizio per il lettore"; il metodo __set__ di un descrittore di dati non viene chiamato quando si esegue una ricerca su una classe. L'associazione viene semplicemente cambiata. –

+23

-1: i metodi statici sono uno strumento prezioso e utile. – Reid

49

Utente kaizer.se era su qualcosa per quanto riguarda la domanda originale. Presi un ulteriore passo avanti in termini di semplicità, in modo che ora richiede solo un singolo decoratore:

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

utilizzati:

class Stats: 
    _current_instance = None 

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

Come indicato, questo modo di creare un singoletto non è un buon design pattern; se ciò deve essere fatto, una fabbrica di metaclassi è un modo molto migliore per farlo. Ero solo eccitato per la prospettiva di una proprietà di classe, quindi, eccolo.

1

seguito con quello che ha scritto KyleAlanHale:

suo esempio grandi opere, fino a quando si cerca di fare:

Stats.singleton = 5 

Questo non vi darà un errore, sovrascriverà la funzione, in modo che quando si digita prossima

single = Stats.singleton 
print single 

otterrete

5 

Penso che tu stia meglio usando la risposta di Kyle senza la decorazione @classproperties.

Problemi correlati