decorators (PEP-614)
Syntax for decorators is limited by getting attributes and calling objects:
decos = {
'id': lambda x: x,
}
@decos['id']
def f(): pass
# SyntaxError: invalid syntax
Python 3.9 (via PEP-614) relaxes with restriction allowing to have any expression as a decorator:
decos = {
'id': lambda x: x,
}
@decos['id']
def f(): pass
f
# <function f at ...>
You can use matrix multiplication to make it confusing (don't try it at home!):
class D:
f = None
def __init__(self, name):
self.name = name
def __call__(self, *args, **kwargs):
# on the first call save the function
if self.f is None:
self.f = args[0]
return self
# on all the next calls call the function
print(f'hello from {self.name}!')
return self.f(*args, **kwargs)
# matrix multiplication logic
def __matmul__(self, other):
return lambda f: self(other(f))
# the second `@` is actually the matrix multiplication
@D('a') @D('b')
def f(): pass
f()
# hello from a!
# hello from b!
You can use a simple wrapper function to have any expression in older python versions:
_ = lambda x: x
@_(D('a') @ D('b'))
def f(): pass