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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With