2010-09-02 12 views
5

Chociaż zdaję sobie sprawę, że nie można odwoływać się do self bezpośrednio w dekoratorze, zastanawiałem się, czy to nie jest dobra praktyka, aby obejść to, ciągnąc go od args[0]. Moje przeczucie jest takie, ale chcę być tego pewien.Czy to jest zła praktyka używać siebie w dekoratorów?

Mówiąc dokładniej, pracuję nad API dla usługi internetowej. Około połowa poleceń wymaga podania tokena, który później można wykorzystać do jego cofnięcia. Chciałbym, aby ten token był parametrem opcjonalnym, a jeśli żaden nie został podany, by go wygenerować. Generowanie tokena wymaga uwierzytelnionego połączenia z serwerem, który potrzebuje danych z obiektu.

Choć wiem, że mogę to zrobić:

def some_command(self, ..., undo_token = None): 
    if undo_token = None: 
     undo_token = self.get_undo_token() 
    ... 
    return fnord 

Czuję, że może być lepszy sposób niż mieć taki sam kod w kilkunastu metod. Moja myśl była napisać dekorator:

@decorator 
def undoable(fn, *args, **kwargs): 
    if 'undo_token' not in kwargs: 
     kwargs['undo_token'] = args[0].get_undo_token() 
    return (fn(*args, **kwargs), kwargs['undo_token']) 

Więc mogę więcej pisać czysto

@undoable 
def some_command(self, ...): 
    ... 
    return foo 

@undoable 
def some_other_command(self, ...): 
    ... 
    return bar 

jestem ustawiania się w górę na kłopoty w dół linii?

+0

+1 za użycie wzoru dekoratora do zaimplementowania "cofania". –

+2

Nic nie jest nie tak z dekoratorem, który ma wymagania dotyczące parametrów dekorowanej funkcji; tylko upewnij się, że jest to udokumentowane. –

Odpowiedz

6

Nie rozumiem co masz kodująca undoable - to nie jest jak dekoratorzy są zazwyczaj kodowane i nie wiem gdzie to @decorator pochodzi (jest tam from youforgottotelluswhence import decorator lub coś jeszcze bardziej zła, dlaczego? Nie mogę znieść użycia from do budowania "sztucznych baniek" zamiast używania pięknych nazw zdobionych? -).

Przy normalnym kodowaniu dekorator, np ...:

import functools 

def undoable(f): 
    @functools.wraps(f) 
    def wrapper(self, *a, **k): 
     tok = k.get('undo_token') 
     if tok is None: 
      tok = k['undo_token'] = self.get_undo_token() 
     return f(self, *a, **k), tok 
    return wrapper 

nie ma absolutnie żadnego problemu nazewnictwa pierwszy, obowiązkowy pozycyjnym argumentu owijki za self i wiele wzmocnienie przejrzystości w użyciu to raczej niż mniej czytelny args[0] .

+1

Następnie sprawdź: http://pypi.python.org/pypi/decorator/2.3.2 – wheaties

+0

+1 "Nie mogę znieść użycia' od' do budowy 'sztucznych oczek " – Pete

+0

Tak, to' od dekoratora importu dekoratora' ** naprawdę ** sprawia, że ​​kod Q jest niemożliwy do zrozumienia w/oa " referencyjny adres URL ", tak jak zawsze robią to" sztuczne bannames "- szkoda, że ​​Michele zdecydował się użyć go w swoich dokumentach, dając użytkownikom tak okropny przykład. Dalej szkoda, że ​​w tym przypadku przynajmniej moduł dekoratora strony trzeciej zmusza argumenty, aby kod był bardzo trudny do naśladowania, podczas gdy prosta składnia Pythona równo rozdziela "funkcję, która jest dekorowana" od "argumentów do opakowania" - ja " d raczej gubią czarną magię dla "zachowania podpisu", niż tracą klarowność kodu poprzez ich umacnianie. –

2

Dekoratory rozszerzają funkcjonalność funkcji, którą dekoruje w sposób ogólny. Jeśli dekoratorzy nie mają żadnych założeń na temat funkcji lub jej argumentów lub kwargów, to jest ona w najbardziej ogólnej formie i może być łatwo wykorzystana z wieloma funkcjami.

Jakkolwiek, jeśli chcesz coś zrobić z tym, co jest przekazywane do funkcji, powinno być w porządku, ale ich przydatność jest ograniczona i może się zepsuć, jeśli zmieniają się podstawowe szczegóły, które zastosowałeś w swoim dekoratorze.

W powyższym dekoratorze, jeśli obiekt usuwa metodę get_undo_token(), konieczne będzie ponowne sprawdzenie również dekoratora. Można to zrobić, ale udokumentować ograniczenia, a także dodać dokumentację do tej metody.

Zrób to tylko, jeśli jest to absolutnie konieczne. Służy do tworzenia bardziej ogólnych dekoratorów.

Powiązane problemy