Psycho Mantys
Psycho Mantys

Reputation: 33

Using a dict as decorators on python

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

Answers (1)

Patrick Haugh
Patrick Haugh

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

Related Questions