Rajeev
Rajeev

Reputation: 46909

decorators in python

I am trying to understand the functioning of decorators. What am i doing wrong in the following code. Please do correct it

As I have understood when aFunction() is called it in turn calls myDecorator() which also makes a call to afunction(). Right?

Also how to pass parameters into afunction()

class myDecorator(object):

    def __init__(self, f):
        print "inside myDecorator.__init__()"
        f(1) # Prove that function definition has completed

    def __call__(self):
        print "inside myDecorator.__call__()"

@myDecorator
def aFunction(*a):
    print a
    print "inside aFunction()"

print "Finished decorating aFunction()"

aFunction(2)

Upvotes: 0

Views: 274

Answers (3)

Rudi
Rudi

Reputation: 19940

Your __call__ method is missing the parameter, which you give to aFunction.

class myDecorator(object):

    def __init__(self, f):
        print "inside myDecorator.__init__()"
        f(1) # Prove that function definition has completed
        self.__function = f

    def __call__(self, *args):
        # the *args magic is here to mirror the original parameter list of
        # the decorated function. But it is better to place here parameter list
        # of the function you want to decorate, in order to minimize error possibilities
        print "inside myDecorator.__call__()"
        return self.__function(*args)

@myDecorator
def aFunction(*a):
    print a
    print "inside aFunction()"

print "Finished decorating aFunction()"

aFunction(1)
aFunction('a', 23, 42)

Upvotes: 2

agf
agf

Reputation: 176750

class myDecorator(object):

    def __init__(self, f):
        print "inside myDecorator.__init__()"
        # save a reference to the real function, so it can be called later
        self.f = f

    def __call__(self, *args, **kwargs):
        print "inside myDecorator.__call__()"
        # call the real function and return its result
        # passing it any and all arguments
        return self.f(*args, **kwargs)

@myDecorator
def aFunction(*a):
    print a
    print "inside aFunction()"

print "Finished decorating aFunction()"

aFunction(1)

print "Finished calling aFunction()

Upvotes: 4

Ethan Furman
Ethan Furman

Reputation: 69031

f, in __init__, needs to be saved, then the __call__ method needs to call it. Something like this:

class myDecorator(object):
    def __init__(self, f):
        print "inside myDecorator.__init__()"
        self.f = f
        print "function has been saved"
    def __call__(self, *args):
        print "inside myDecorator.__call__()"
        result = self.f(args)
        print "done with f()"
        return result

@myDecorator
def aFunction(*a):
    print a
    print "inside aFunction()"

aFunction(1)

What happens with decoration is that the original function is replaced with whatever the decorator returns. Your original code, however, was not saving any reference to aFunction so it was getting lost.

Upvotes: 1

Related Questions