2009-11-08 3 views
29

chcęPython: @staticmethod z @property

Stats.singleton.twitter_count += 1 

i pomyślałem mogłem zrobić

class Stats: 
    singleton_object = None 

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

Ale to zgłasza wyjątek:

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

gdzie zdefiniowano "singleton_object"? – tonfa

+3

gdzie jest zdefiniowany "własny"? – tonfa

+2

define "nie działa" – u0b34a0f6ae

Odpowiedz

8

Singletons są bezcelowe w Pythonie.

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 

Pythona int s są differnt od prostych object s, więc nie zawsze jest takie proste. Ale dla twoich potrzeb, to wydaje się wystarczające:

class Stats: 
    twitter_count = 0 

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

Mam trochę backstory, w tym chcę mieć db AppEngine.Obiekt modelu to singleton (tylko jeden obiekt Stats w bazie danych). Więc muszę mieć co najmniej jedną instancję w pamięci. –

+1

Nie rozumiem tego. Kiedy za tym stoi DB, wszystkie instancje współdzielą już ten sam stan, stan rzędu w DB. Dwa wystąpienia mogą nie być identyczne, ale każdy ORM, który zasłużyłby na to nazwisko, upewni się, że zmiana również spowoduje zmianę drugiego. –

+32

Wszyscy słyszysz, jak ludzie mówią, że statyczne metody i singletony są bez sensu w Pythonie, Yadda, Yadda. To bzdura. Singleton jest prawidłowym, potrzebnym wzorem. Co "my", większa społeczność programistów chce wiedzieć, "jak" powinniśmy robić to "właściwą drogę". Każda odpowiedź, która nie odpowiada bezpośrednio, jest, jak sądzę, nieprzydatna. Ja, na przykład, jestem zaskoczony tą kwestią. :-) Wsparcie! – 010110110101

6

Metody statyczne nie robić sens w języku Python. Dzieje się tak dlatego, że nie robią nic, czego nie potrafią metody klasowe, a metody klasowe są znacznie łatwiejsze do rozszerzenia w przyszłości (gdy metody wielu klas używają się nawzajem itd.).

Potrzebna jest po prostu właściwość metody klasy.

Mam właściwość metody klasy z mojego kodu tutaj. To jest tylko do odczytu tylko, że było wszystko, co potrzebne (tak reszta to ćwiczenie dla czytelnika):

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

Nie sądzę, że istnieje odpowiedź na twoje "ćwiczenie dla czytelnika"; metoda __set__ deskryptora danych nie jest wywoływana podczas wyszukiwania w klasie. Wiązanie właśnie się zmienia. –

+23

-1: metody statyczne są cennym i przydatnym narzędziem. – Reid

49

Użytkownik kaizer.se był na czymś tak daleko, jak pierwotne pytanie idzie. Wziąłem go o krok dalej pod względem prostoty, tak, że teraz wymaga tylko jednego dekorator:

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

Zastosowanie:

class Stats: 
    _current_instance = None 

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

Jak już wspomniano, w ten sposób tworzenia pojedyncza nie jest dobry wzór projektu; jeśli to musi być zrobione, fabryka metaklasy to o wiele lepszy sposób na zrobienie tego. Byłem po prostu podekscytowany perspektywą własności klasowej, więc jest.

1

W nawiązaniu do tego, co KyleAlanHale napisał:

Jego przykład działa świetnie, dopóki nie spróbujesz zrobić:

Stats.singleton = 5 

nie daje błąd, to zastąpienie funkcji, tak aby po wpisaniu kolejnego

single = Stats.singleton 
print single 

Dostaniesz

5 

Myślę, że najlepiej będzie, jeśli użyjesz odpowiedzi Kyle'a bez dekoracji @classproperties.