Я многому научился из этого вопроса, спасибо всем. Разве ответ не состоит в том, чтобы поставить пустые скобки в первый @Cache
? Затем вы можете переместить параметр function
в __call__
.
class Cache(object):
def __init__(self, max_hits=10, timeout=5):
self.max_hits = max_hits
self.timeout = timeout
self.cache = {}
def __call__(self, function, *args):
# Here the code returning the correct thing.
@Cache()
def double(x):
return x * 2
@Cache(max_hits=100, timeout=50)
def double(x):
return x * 2
Хотя я думаю, что этот подход проще и лаконичнее:
def cache(max_hits=10, timeout=5):
def caching_decorator(fn):
def decorated_fn(*args ,**kwargs):
# Here the code returning the correct thing.
return decorated_fn
return decorator
Если вы забыли скобки при использовании декоратора, к сожалению, вы все равно не получите сообщение об ошибке до времени выполнения, поскольку параметры внешнего декоратора передаются функции, которую вы пытаетесь декорировать. Затем во время выполнения внутренний декоратор жалуется:
TypeError: caching_decorator () принимает ровно 1 аргумент (задано 0).
Однако вы можете это уловить, если знаете, что параметры вашего декоратора никогда не будут вызываться:
def cache(max_hits=10, timeout=5):
assert not callable(max_hits), "@cache passed a callable - did you forget to parenthesize?"
def caching_decorator(fn):
def decorated_fn(*args ,**kwargs):
# Here the code returning the correct thing.
return decorated_fn
return decorator
Если вы сейчас попробуете:
@cache
def some_method()
pass
Вы получаете AssertionError
по объявлению.
По касательной я наткнулся на этот пост в поисках декораторов, которые украшают классы, а не классы, которые украшают. В случае, если кто-то еще делает, этот вопрос будет полезен.