2013-07-02 9 views
15

Mam klasy modelu django, który utrzymuje stan jako prosta właściwość. Dodałem kilka właściwości pomocnika do klasy, aby uzyskać dostęp do stanów zagregowanych - np. is_live zwraca wartość false, jeśli stan jest jednym z ['closed', 'expired', 'deleted'] itd.Pyton idiomatyczny - właściwość lub metoda?

W wyniku tego mój model ma kolekcję właściwości is_, które wykonują bardzo proste wyszukiwania na wewnętrznych właściwościach obiektu.

Chcę teraz dodać nową właściwość, is_complete - która jest semantycznie taka sama jak wszystkie inne właściwości - sprawdzanie boolowskie stanu obiektu - jednak ta kontrola wymaga uzależnienia od ładowania (jeden-do-wielu) obiektów podrzędnych, sprawdzanie ich stanu i raportowanie na podstawie wyników - tj. ta właściwość faktycznie wykonuje niektóre (więcej niż jedno) zapytanie bazy danych i przetwarza wyniki.

Czy nadal można modelować jako właściwość (używając dekoratora @property), czy też powinienem zrezygnować z dekoratora i pozostawić go jako metodę?

Pro użycia właściwości jest to, że jest semantycznie zgodne z wszystkich innych właściwości is_.

Pro za pomocą metody polega na tym, że wskazuje ona innym programistom, że jest to coś, co ma bardziej złożoną implementację i dlatego powinno być używane oszczędnie (tj. Nie wewnątrz pętli for..).

from django.db import models 

class MyModel(models.Model): 

    state = CharField(default='new') 

    @property 
    def is_open(self): 
     # this is a simple lookup, so makes sense as a property 
     return self.state in ['new', 'open', 'sent'] 

    def is_complete(self): 
     # this is a complex database activity, but semantically correct 
     related_objects = self.do_complicated_database_lookup() 
     return len(related_objects)==0 

EDIT: I pochodzić z tła .NET pierwotnie, gdzie podział się znakomicie zdefiniowane przez Jeff Atwood jak

„jeśli jest jakaś szansa na cały ten kod może tarło klepsydrę, to na pewno powinna być metodą. "

EDIT 2: nieznaczna zmiana na pytanie - byłoby to problemem, aby go jako metoda, zwana is_complete, tak że nie są mieszane właściwości i metody z podobnych nazwach - czy to tylko mylące?

Tak - to będzie wyglądać mniej więcej tak:

>>> m = MyModel() 
>>> m.is_live 
True 
>>> m.is_complete() 
False 
+0

Myślę, że to wciąż ma sens. Czy możesz buforować wynik jako 'self._is_complete' lub czy jest on obliczany wiele razy? Czy możesz wykonywać obliczenia w tle lub czy obliczenia są ważne tylko wtedy, gdy nieruchomość jest oceniana? –

+0

@ JaceBrowning: Miałem dokładnie ten sam pomysł (proszę zobaczyć moją odpowiedź). Zakładałem, że to jest w porządku (jeśli nie, zawsze można je wyczyścić). – Tadeck

+0

@ Tadeck: bez obaw. Nie wiem wystarczająco dużo o 'django', aby wiedzieć, czy ta aplikacja ma sens. –

Odpowiedz

9

To jest w porządku, aby to zrobić, zwłaszcza jeśli będzie można użyć następującego wzoru:

class SomeClass(models.Model): 
    @property 
    def is_complete(self): 
     if not hasattr(self, '_is_complete'): 
      related_objects = self.do_complicated_database_lookup() 
      self._is_complete = len(related_objects) == 0 
     return self._is_complete 

Wystarczy pamiętać, że „buforuje” wyniki, więc pierwsze wykonanie wykonuje obliczenia, ale później wykorzystuje istniejące wyniki.

+0

Dzięki @tadeck - Myślę, że jest to prawidłowe podejście, ale na refleksji, co powinienem był zapytać, czy ma mieszane właściwości i metody (z tą samą konwencją nazewnictwa - patrz pytanie 2)? –

+0

@ HugoRodger-Brown: Pep8 wspomina, że ​​obie metody i zmienne instancji nas nazywają "underscore_seperate_names", więc tak, to absolutnie w porządku. Ponieważ zarówno metoda, jak i zmienna zwracają wartość logiczną, 'is_' jest tym, czego oczekiwałbym przedrostkiem. – TyrantWave

+0

@TyrantWave: Ogólnie się zgadzam. Plus, dobre (lub średnie) IDE są w stanie powiedzieć, kiedy coś jest własnością, metodą lub jakimś innym atrybutem, i wyświetlić go poprawnie. Ponadto można oczekiwać, że metody 'check_' nie zwrócą niczego (technicznie:' Brak') lub zaakceptują wywołanie zwrotne, które następnie zostanie przekazane do wyniku (w przypadku podejścia opartego na zdarzeniach). Ale PEP8 stwierdza także: "Spójność w projekcie jest ważniejsza, najważniejsza jest spójność w ramach jednego modułu lub funkcji." Lepiej więc mieć spójną bibliotekę niż spełniać oczekiwania innych ludzi. – Tadeck