2015-08-16 16 views
5

Próba określenia, czy powinienem spróbować użyć dekoratora lub innego sposobu Pythonic, aby zredukować kod wykonywany przez wiele moich funkcji. Chciałbym, aby te funkcje były w stanie wywołać tylko jedną funkcję na początku każdej funkcji lub "udekorować" początek każdej funkcji. Nigdy wcześniej nie używałam dekoratora i staram się zaimplementować ten pomysł dekorowania w sposób pytonowy, aby zredukować wspólny zestaw kodów akcji w każdej funkcji.Czy powinienem ozdobić funkcję?

Mam wiele funkcji, które wykonają ten sam zestaw kroków na początku funkcji. Nie ma jednak pewne obawy struktura wspólnego kodu, który sprawia, że ​​ten „dekorator” pomysł trudne:

  • Funkcje są w klasie podrzędnej klasy nadrzędnej.

  • Wspólne rozkazy między funkcjami odniesienia nazwy zmiennych , które są specyficzne dla tej funkcji (lecz podzbiór nazwa funkcji ).

  • Wspólne polecenia muszą wrócić do osoby dzwoniącej i nie wykonywać żadnych dodatkowych funkcji podrzędnych, jeśli spełniony jest określony warunek. („Jeśli jobj” blok kod próbki)

dla zmiennej przykłady/atrybutów funkcja dziecko get_nas_server (samo) wykorzysta „nas_server” zmienne warianty w wspólnego zestawu kodu. Odejmowanie get_ od nazwy funkcji ujawnia podstawę nazwy zmiennej, która ma być użyta we wspólnym zbiorze kodu. Przykład Nazwy zmiennych i obiektów atrybutami pochodzą z „get_nas_server” nazwa funkcji:

nas_server
nas_server.json
self.nas_server (Attribute)

Oto wspólny kod z jedną z funkcji:

 #################################################################### 
     def get_nas_server(self): 
     #################################################################### 
      """\nGets COMMAND nas_server and places data into self.nas_server""" 

      try: 
       self.nas_server 
       return self.nas_server 
      except AttributeError: 
       pass 
      self.get_file_cmd('nas_server') 
      jobj = self.fresh_json('nas_server.json') 
      if jobj : 
       self.nas_server = jobj 
       return self.nas_server 
      self.get_file_cmd('get_nas_server') 

Wszystko poniżej tego kodu w funkcji jest specyficzne dla celu funkcji i nie jest odpowiednie do dyskusji tutaj. Zasadniczo próbuję zrobić cały ten kod powyżej wielokrotnego użytku w moich funkcjach, ale kod musi mieć zmienne i atrybuty zmienione w zależności od nazwy funkcji.

Dziękuję za przeczytanie, jeśli dotarłeś tak daleko i dziękuję za wszelką pomoc.

Odpowiedz

2

Wygląda jak coś można zdefiniować jako metody pomocnika w klasie nadrzędnej:

class Parent(object): 
    def _get_something(name): 
     try: 
      return getattr(self, name) 
     except AttributeError: 
      pass 
     self.get_file_cmd(name) 
     jobj = self.fresh_json(name+'.json') 
     if jobj : 
      setattr(self, name, jobj) 
      return jobj 
     self.get_file_cmd('get_'+name) 

Jak ten fragment pokazuje, można korzystać z getattr(), setattr() i hasattr() funkcji odwołać atrybutów obiektu według nazwy.

+0

Dzięki za wejście. Kod, który ma zostać dodany do istniejącej funkcji, musi mieć możliwość powrotu do pierwotnego wywołującego i nie wykonywać już kodu, jeśli spełnione są określone warunki. Ten "powrót", jeśli wymaganie warunku nie wydaje się możliwe z pomocą metody pomocnika. – Fragtzack

+0

@Fragtzack Prawda, ale możesz to zrobić w kilku liniach w funkcji, która wywołuje pomocnika. – augurar

+0

ok, spróbuje tego. W funkcji, która wywołuje tego pomocnika, nazywam tego pomocnika po prostu self._get_something ('nas_server')? – Fragtzack

1

Możesz użyć dekoratora wewnątrz swojej klasy, jeśli początkowe elementy księgowości są zbyt specyficzne dla tej klasy. Za każdym razem, gdy musisz wykonać to wstępne sprawdzenie wewnątrz metody klasy, możesz po prostu ozdobić ją dekoratorem auto_nas, który dodałem poniżej. Zakres tego opakowania, jak przypuszczam, dotyczy tylko tej klasy. W przeciwnym razie możesz przenieść go poza klasę, ale pamiętaj, aby zmienić (self=None), jeśli masz zamiar to zrobić.

class YourMainClass(): 
    # This is your main class inside which all the methods are defined. 

    def auto_nas(func): 
     # This wrapper function will be called instead of your class methods. 
     def wrap(self): 
      # All your bookkeeping stuff goes here. 
      try: 
       self.nas_server 
       return self.nas_server 
      except AttributeError: 
       pass 
      self.get_file_cmd('nas_server') 
      jobj = self.fresh_json('nas_server.json') 
      if jobj : 
       self.nas_server = jobj 
       return self.nas_server 
      self.get_file_cmd('get_nas_server') 
      # Things went well - we shall call the actual method. 
      return func(self) 
     return wrap 

    @auto_nas 
    def get_nas_server(self): 
     # This is one of your methods that require bookkeeping 
     pass 

Zauważ także self wewnątrz funkcji owijki. Jest on automatycznie przekazywany jako argument przez Python, dzięki czemu można uzyskać dostęp do wszystkich atrybutów specyficznych dla instancji z wnętrza tego dekoratora. Po raz kolejny jest to odpowiednie, jeśli Twój dekorator musi wykonywać zadania specyficzne dla każdego wystąpienia klasy. Jeśli tak nie jest, możesz po prostu umieścić cały ten kod w funkcji i wywoływać go za każdym razem, kiedy tylko chcesz.

0

Dziękuję firmie Augurar za wskazanie we właściwym kierunku. W końcu utworzyłem metodę stub w klasie nadrzędnej. Wystarczyło wywołać metodę z odpowiednią techniką, aby "rozszerzyć" metodę macierzystą. Następnie wywołanie tej metody z klasy podrzędnej z super() Musi być właściwa nazwa dla tej techniki? zastąpienie metody? metoda przedłużyć?

Oto metoda klasy rodzic przeważnie jak sugeruje Augurar:

########################################################################### 
def get_stub(self,fcmd): 
########################################################################### 
    try: 
     return getattr(self, fcmd) 
    except AttributeError: 
     pass 
    jobj = self.fresh_json(fcmd + '.json') 
    if jobj : 
     setattr(self, fcmd, jobj) 
     return jobj 
    if not self.get_file_cmd(fcmd): 
     self.log.error("{} not found".format(fcmd)) 
     return False 

Oto sposób, w jaki sposób dziecko korzysta z tej metody parent:

#################################################################### 
def get_nas_server(self): 
#################################################################### 
    super().get_stub('nas_server') 
    #bunch of child method specific code below here 
Powiązane problemy