Próbowałem znaleźć odpowiedź tutaj, ale nie mogłem.Python decorator @func(). Błąd składni atrybutu
@obj.funC# works
@obj.func(**kwargs) #works
@obj.func1(**kwargs).func2 #-> syntax error
Nie rozumiem dlaczego trzecia forma jest SyntaxError, wydaje się dla mnie nie naruszają jakiekolwiek składni Pythona i to jest dla mnie jasne, co użytkownik chce zrobić (patrz przykład poniżej).
Spojrzałem na pep 0318 realizacji dekoratora, ale nie znalazłem żadnych odpowiedzi.
Tutaj ryczeć, byłoby przykładem użycia:
class ItemFunc(object):
def __init__(self, fcall=None, **kwargs):
self.defaults = kwargs
self.fcall = None
def __call__(self, *args, **kwargs):
kwargs = dict(self.defaults, **kwargs)
# do something more complex with kwargs
output = self.fcall(*args, **kwargs)
# do something more with output
return output
def caller(self, fcall):
""" set call and return self """
self.call = fcall # after some check obviously
return self
def copy(self,**kwargs):
kwargs = dict(self.defaults, **kwargs)
return self.__class__(self.fcall, **kwargs)
def copy_and_decorate(self, **kwargs):
return self.copy(**kwargs).caller
niż można użyć ItemFunc jako dekorator:
@ItemFunc
def plot(**kwargs):
pass
redcross = plot.copy(color="red", marker="+")
@redcross.caller
def plot_data1(**kwargs):
pass
bluecross = redcross.copy(color="blue")
@bluecross.caller
def plot_data2(**kwargs):
pass
ale dlaczego to po 'krótki składnia cut' jest zabronione:
@redcross.copy(color="blue").caller
def plot_data2(**kwargs):
pass
Ale mogę zrobić:
@redcross.copy_and_decorate(color="blue")
def plot_data2(**kwargs):
pass
Pierwsza forma wygląda ładniej, przynajmniej lepiej rozumiem intencje z tyłu.
Tak, to bardziej problem filozoficzny. Dla mnie wykończenie dekoratora czymś takim jak .getter lub .caller (jak w moim przykładzie) wyjaśnia, co chcemy zrobić, podczas wywoływania funkcji, która na końcu wysyła metodę .caller (mój przykład ponownie) jest dozwolone, ale mniej czytelny. nie sądzisz? – user3240484
@ user3240484: Widzę, dokąd zmierzasz; ale być może zamiast używać atrybutu, ''_call__' zwróci rzeczywisty dekorator, co również obsługuje' __call__'? –
Masz rację, ale jeśli spojrzysz na mój przykład, metoda __call__ już działa jak dekorator funkcji fcall, aby zachować funkcję podobną do funkcji dla użytkowników. Mógłbym zastąpić __call__ przez funkcję połączenia i użyć __call__, aby zwrócić dekoratora, ale to, co tam zyskuję, tracę tam. dzięki – user3240484