xotl.tools.decorator.meta
- Decorator-making facilities¶
Decorator-making facilities.
This module provides a signature-keeping version of the
xotl.tools.decorators.decorator()
, which is now deprecated in favor of
this module’s version.
We scinded the decorator-making facilities from decorators per se to allow the
module xotl.tools.deprecation
to be used by decorators and at the same
time, implement the decorator deprecated()
more
easily.
-
xotl.tools.decorator.meta.
decorator
(caller)[source]¶ Eases the creation of decorators with arguments. Normally a decorator with arguments needs three nested functions like this:
def decorator(*decorator_arguments): def real_decorator(target): def inner(*args, **kwargs): return target(*args, **kwargs) return inner return real_decorator
This decorator reduces the need of the first level by comprising both into a single function definition. However it does not removes the need for an
inner
function:>>> @decorator ... def plus(target, value): ... from functools import wraps ... @wraps(target) ... def inner(*args): ... return target(*args) + value ... return inner >>> @plus(10) ... def ident(val): ... return val >>> ident(1) 11
A decorator with default values for all its arguments (except, of course, the first one which is the decorated
target
) may be invoked without parenthesis:>>> @decorator ... def plus2(func, value=1, missing=2): ... from functools import wraps ... @wraps(func) ... def inner(*args): ... print(missing) ... return func(*args) + value ... return inner >>> @plus2 ... def ident2(val): ... return val >>> ident2(10) 2 11
But (if you like) you may place the parenthesis:
>>> @plus2() ... def ident3(val): ... return val >>> ident3(10) 2 11
However, this is not for free, you cannot pass a single positional argument which type is a function:
>>> def p(): ... print('This is p!!!') >>> @plus2(p) ... def dummy(): ... print('This is dummy') Traceback (most recent call last): ... TypeError: p() takes ...
The workaround for this case is to use a keyword argument.