Annie Hua
Annie Hua

Reputation: 59

In Python, how can I get the name of the function passed to my decorator with parameters?

I am trying to create a decorator that will validate if the parameter exist and retrieve the name of the method that is decorated.

I was able to access the name of the method in my second layer of the function but not the first.

For example, I have this decorator

def p_decorate(name, *a, **k):
    print(name + ' is at object: ')
    print a #I would like to get the method object here
    def fn(*a, **k)
        print a #object prints here instead
    return fn
return p_decorate

I have this class I would like to decorate

class Person(object):
    @p_decorate('John')
    def get_fullnameobject(self):
        return self.name

I expect it to print:

John is at object: (<function get_fullnameobject at 0x000000003745A588>,)
(<function get_fullnameobject at 0x000000003745A588>,)

but the output is:

John is at object: ()
(<function get_fullnameobject at 0x000000003745A588>,)

Upvotes: 1

Views: 221

Answers (3)

Jorge Salazar
Jorge Salazar

Reputation: 1

You can use function.__name__ to get the name of the function. So in your case it would be:

print(name.__name__ + ' is at object: ')

Upvotes: 0

chepner
chepner

Reputation: 531085

You need another nested function to define a decorator that takes arguments.

def p_decorate(name):
    def _(f):
        print(name + ' is at object: ')
        print f
        def fn(*a, **k):
            # Do something, but ultimately you probably want to call f
            ...
        return fn
    return _

p_decorate("John") returns the actual decorator, which takes get_fullnameobject as its f argument and returns the new fn object to bind to get_fullnameobject. Without decorator syntax, the usage looks like

def get_fullnameobject(self):
    return self.name

get_fullnameobject = p_decorate("John")(get_fullnameobject)

Upvotes: 1

heemayl
heemayl

Reputation: 42007

The function p_decorate is being called with only argument John (*a and **k both will be empty), hence you're getting an empty tuple for a.

Just to note, the returned fn callable is being called with the get_fullnameobject callable afterwards.

More importantly, your current implementation is incomplete as you can never call the method -- you need another closure to actually do that.

Upvotes: 1

Related Questions