Skip to content Skip to sidebar Skip to footer

Decorator Error: NoneType Object Is Not Callable

I wrote a function decorator like this: def tsfunc(func): def wrappedFunc(): print '%s() called' % func.__name__ return func() return wrappedFunc() @tsfunc

Solution 1:

You should return the wrapper function itself, not its result:

def tsfunc(func):
    def wrappedFunc():
        print '%s() called' % func.__name__
        return func()
    return wrappedFunc   # Do not call the function, return a reference instead

Decorators replace the decorated item with the return value of the decorator:

@tsfunc
def foo():
    # ....

is equivalent to:

def foo():
    # ....
foo = tsfunc(foo)

which expands to (in your code):

foo = wrappedFunc()

so you were replacing the function foo with the result of the wrappedFunc() call, not with wrappedFunc itself.


Solution 2:

You need to remove the parentheses in

return wrappedFunc

The decorator is supposed to return the wrapper function, not call it.

With this fix, the code produces:

foo() called
foo() called

Solution 3:

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


Solution 4:

you use this syntax

def tsfunc(func):
    def wrappedFunc():
        print '%s() called' % func.__name__
        return func()
    return wrappedFunc # not use wrappedFunc() becaues Because this function runs at the this time 

@tsfunc
def foo():
    pass

foo()  # 

Post a Comment for "Decorator Error: NoneType Object Is Not Callable"