Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected SyntaxError with decorators

Tags:

python

Here the goal is to call a global function as a decorator.

#coding: utf-8
def Test(method_to_decorate):
    print 'Decorator'
    def wrapper(self):
        return method_to_decorate(self)
    return wrapper


class Smth(object):
    def Test(self):
        print 'NOT a decorator!'

    a=globals()['Test']

    #@globals()['Test'] --> SyntaxError
    @a # works fine
    def Fun(self):
        print "Smth.Fun()"

l = Smth()
l.Fun()

Using the uncommented approach works fine while @globals()['Test'] gives SyntaxError. Why? I'm quite sure Test exists in globals().

The thing after @ must be a function accepting another function as one of its arguments, am I right? globals()['Test'] is such a function, isn't it? Then, in my opinion, @globals()['Test'] must be correct (logically correct).

Edit

This works as expected:

def Ex(*args):
    print 'Ex({})'.format(args) 
globals()['Ex']('hello') # just calling a function

While a decorator is used, a function is called. We can call functions as above but can't use a decorator like this. Maybe this is some sort of a Python bug or logic misorganisation?

like image 943
ForceBru Avatar asked Aug 15 '26 12:08

ForceBru


1 Answers

It's a SyntaxError because Python's grammar explicitly does not allow that; the tokens on the right of @ are not an expression. 1 Instead, valid syntax is:

decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE

(A phrase enclosed in square brackets ([ ]) means zero or one occurrences (in other words, the enclosed phrase is optional).) 2

Following from the above, you can get this to work by converting globals()['Test'] to a dotted name. The following examples should work:

g = globals()
@g.get('Test')
def Fun(self):
    pass

x = globals()['Test']
@x
def Fun(self):
  pass

Or, as you noticed, you can just skip the syntactic sugar and decorate manually, which is probably the least bad option.

like image 155
Ceasar Bautista Avatar answered Aug 18 '26 03:08

Ceasar Bautista



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!