A little late , but hope this helps, Extending on why the answer provided is accepted
as the error states, 'NoneType' means that the instance/object we are trying to call has no type (it is not a function/int/boolean/class/instance ). Its type is just 'None'
So to summarize, decorators are nothing but extended use of closures with functions being treated as first class citizens (You could get a detail view on closures
It basically means a decorator expects a function to be returned , say a wrapper in most cases, with the original function being unaltered and being called withing the decorator
def tsfunc(func):
def wrappedFunc():
print '%s() called' % func.__name__
return func()
return wrappedFunc() -> Here the function is not returned but called eventually
@tsfunc
def foo():
pass
foo() - > calling this again doesnt make sense to trigger the decorator, since a reference for the method foo is enough. Hence foo works fine but foo() doesn't (method call has completed already but no value is returned) If you try like this, you would see that the variable has 'None' type
def tsfunc(func):
def wrappedFunc():
print '%s() called' % func.__name__
return func()
return wrappedFunc -- Here I made the correction
@tsfunc
def foo():
pass
var1 = foo()
print(var1)
This what happened with the call to foo() when you had the incorrect way of calling the wrapper function rather than returning just the function
So for a decorator to function as per the norms, it should return a wrapper function with the original function being unaltered. And hence it should be rewritten as per the accepted answer