dekoratorów funkcje te funkcje powrotu. Kiedy "przekazanie parametru do dekoratora" faktycznie wykonywane jest wywołanie funkcji, która zwraca dekorator. Tak więc decAny()
powinna być funkcją, która zwraca funkcję, która zwraca funkcję.
To mogłoby wyglądać tak:
import functools
def decAny(tag):
def dec(f0):
@functools.wraps(f0)
def wrapper(*args, **kwargs):
return "<%s> %s </%s>" % (tag, f0(*args, **kwargs), tag)
return wrapper
return dec
@decAny('xxx')
def test2():
return 'test1XML'
Przykład:
>>> print(test2())
<xxx> test1XML </xxx>
Należy pamiętać, że oprócz ustalenia konkretnego problemu ty uderzanie ja również poprawić swój kod nieco dodając *args
i **kwargs
jako argumenty funkcji opakowanej i przekazywanie ich do wywołania f0
wewnątrz dekoratora. Dzięki temu można udekorować funkcję, która akceptuje dowolną liczbę argumentów pozycyjnych lub nazwanych i nadal będzie działała poprawnie.
Można przeczytać o functools.wraps()
tutaj:
http://docs.python.org/2/library/functools.html#functools.wraps
Pomyśl o tym w ten sposób: Przed wami jeszcze _get_ do dekoracji 'test2', dzwonisz' decAny ('xxx') '. Ale 'decAny' przyjmuje funkcję,' f0', a nie ciąg znaków. Tak więc w pewnym momencie, 'f0()' spróbuje wywołać ''xxx''. – abarnert
OK, ale jak w dekoratorze bez parametrów, dlaczego kompilator nie zakłada, że pierwszym parametrem jest funkcja klienta ... – ZEE
Nie jest to kwestia parametrów. Jeśli masz '@ decAny', to po prostu używając' decAny' jako dekoratora. Ale jeśli masz '@decAny()', to nazywa się 'decAny', zanim zdążysz się dekorować, tak samo jak' @decAny ('xxx') '. (To jest tak, jak przekazujesz funkcje jako wartości, przechowujesz je w zmiennych itp., A nie wywołując je.) – abarnert