Reputation: 33
There some way to use a dict as a decorator on python using the default "@" syntax?
Like something like:
from functools import wraps
def deco(f):
@wraps(f)
def wrapper(*args, **kwargs):
print("WRAPPER")
return f(*args, **kwargs)
return wrapper
X={ "deco": deco }
# Working
@deco
def f():
pass
# Not Working: SyntaxError: invalid syntax
@X["deco"]
def y():
pass
f()
y()
If change to use get() on the dict, this work, but something like this dont:
# Not working: SyntaxError: invalid syntax
@X.get("deco").require(http_exception=403)
def y():
pass
There some way for this syntax work or/and why not working?
Upvotes: 0
Views: 141
Reputation: 60974
The syntax was intentionally restricted. See PEP-0318:
The decorator statement is limited in what it can accept -- arbitrary expressions will not work. Guido preferred this because of a gut feeling.
The current syntax also allows decorator declarations to call a function that returns a decorator:
The email the PEP links says:
I have a gut feeling about this one. I'm not sure where it comes from, but I have it. It may be that I want the compiler to be able to recognize certain decorators.
So while it would be quite easy to change the syntax to @test in the future, I'd like to stick with the more restricted form unless a real use case is presented where allowing @test would increase readability. (@foo().bar() doesn't count because I don't expect you'll ever need that).
So the creator/lead contributor to the language decided that allowing any expression to serve as a decorator would lead to difficult to read code.
It's also never necessary. You can always do
my_deco = X.get("deco").require(http_exception=403)
@my_deco
def somefunc():
...
Upvotes: 3