jak zrobić dekorator warunkowy w Pythonie 2.6
Czy można warunkowo dekorować funkcję. Na przykład, chcę ozdobić funkcję foo()
funkcją timera (timeit
) tylko doing_performance_analysis jest True
(patrz kod psuedo poniżej).
if doing_performance_analysis:
@timeit
def foo():
"""
do something, timeit function will return the time it takes
"""
time.sleep(2)
else:
def foo():
time.sleep(2)
5 answers
Dekoratory to po prostu dekoratory, które zwracają zamiennik, opcjonalnie tę samą funkcję, owijkę lub coś zupełnie innego. W związku z tym można utworzyć dekorator warunkowy:
def conditional_decorator(dec, condition):
def decorator(func):
if not condition:
# Return the function unchanged, not decorated.
return func
return dec(func)
return decorator
Teraz możesz go używać tak:
@conditional_decorator(timeit, doing_performance_analysis)
def foo():
time.sleep(2)
Dekoratorem może być również Klasa:
class conditional_decorator(object):
def __init__(self, dec, condition):
self.decorator = dec
self.condition = condition
def __call__(self, func):
if not self.condition:
# Return the function unchanged, not decorated.
return func
return self.decorator(func)
Tutaj metoda __call__
odgrywa taką samą rolę jak zwracana funkcja zagnieżdżona decorator()
w pierwszym przykładzie, a parametry dec
i condition
są tutaj przechowywane jako argumenty na instancja do momentu zastosowania dekoratora.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-27 13:06:21
Dekorator jest po prostu funkcją zastosowaną do innej funkcji. Można go zastosować ręcznie:
def foo():
# whatever
time.sleep(2)
if doing_performance_analysis:
foo = timeit(foo)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-23 17:23:07
A może:
def foo():
...
if doing_performance_analysis:
foo = timeit(foo)
Wyobrażam sobie, że można nawet zawinąć to do dekoratora, który wziąłby flagę logiczną i inny dekorator, i zastosowałby ten ostatni tylko wtedy, gdy flaga jest ustawiona na True
:
def cond_decorator(flag, dec):
def decorate(fn):
return dec(fn) if flag else fn
return decorate
@cond_decorator(doing_performance_analysis, timeit)
def foo():
...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-23 17:27:10
ODPOWIEDŹ Blckknghta jest świetna, jeśli chcesz sprawdzić za każdym razem, gdy wywołujesz funkcję, ale jeśli masz ustawienie, które możesz przeczytać raz i nigdy się nie zmieni, możesz nie chcieć sprawdzać Ustawienia za każdym razem, gdy wywoływana jest funkcja. W niektórych naszych wysokowydajnych demonach w pracy napisałem dekorator, który sprawdza plik ustawień raz, gdy plik Pythona jest ładowany po raz pierwszy i decyduje, czy powinien go zawijać, czy nie.
Oto przykład
def timed(f):
def wrapper(*args, **kwargs):
start = datetime.datetime.utcnow()
return_value = f(*args, **kwargs)
end = datetime.datetime.utcnow()
duration = end - start
log_function_call(module=f.__module__, function=f.__name__, start=__start__, end=__end__, duration=duration.total_seconds())
if config.get('RUN_TIMED_FUNCTIONS'):
return wrapper
return f
Zakładając, że log_function_call rejestruje połączenie do bazy danych, pliku dziennika lub cokolwiek innego i tego config.get ('RUN_TIMED_FUNCTIONS') sprawdza twoją globalną konfigurację, a następnie dodanie dekoratora @ timed do funkcji sprawdzi raz przy ładowaniu, aby sprawdzić, czy masz czas na tym serwerze, środowisku itp. a jeśli nie, to nie zmieni to wykonania funkcji na produkcji lub w innych środowiskach, w których zależy ci na wydajności.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-16 22:15:11
use_decorator = False
class myDecorator(object):
def __init__(self, f):
self.f = f
def __call__(self):
print "Decorated running..."
print "Entering", self.f.__name__
self.f()
print "Exited", self.f.__name__
def null(a):
return a
if use_decorator == False :
myDecorator = null
@myDecorator
def CoreFunction():
print "Core Function running"
CoreFunction()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-17 00:10:41