Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the class name of a decorated class method

Consider this scenario:

import functools

def wrapmethod(f):
    @functools.wraps(f)
    def wrap(*args, **kwargs):
        print '>> %s' % (f.func_name)

        # Here I'll do pre-processing
        r = f(*args, **kwargs)
        # Here I'll do post-processing

        return r

    return wrap

@wrapmethod
def foo():
    pass

class Test(object):
    @wrapmethod
    def foo(self):
        pass

test = Test()
test.foo()
foo()

It'll output this, as you can see executed in http://codepad.org/Y4xXyjJO:

>> foo
>> foo

I want to know a way to print out Test.foo in the first line, indicating the class which the method is linked to.

Any ideas? Is it ever possible?

Thank you in advance.

like image 419
Paulo Freitas Avatar asked Feb 22 '11 07:02

Paulo Freitas


1 Answers

In fact, you can use inspect module to get the signature of a function, and supposing that you are following the convention of referring to the class object by the first argument 'self', you can do the following :

import inspect  
def print_name(*_args):
    def _print_name(fn):
        def wrapper(*args, **kwargs):
            try :
                is_method   = inspect.getargspec(fn)[0][0] == 'self'
            except :
                is_method   = False

            if is_method :
                name    = '{}.{}.{}'.format(fn.__module__, args[0].__class__.__name__, fn.__name__)
            else :
                name    = '{}.{}'.format(fn.__module__, fn.__name__)

            print (name)
            return  fn(*args,**kwargs)
        return wrapper
    return _print_name

this will print the method module, class and name or just the module and name, if this is a function

From python 3.3 onward, fn.__qualname__ can be used to get the qualified name of the function/method.

def print_name(*args):
     def _print_name(fn):
         def wrapper(*args, **kwargs):
             print('{}.{}'.format(fn.__module__, fn.__qualname__))
             return fn(*args, **kwargs)
         return wrapper
     return _print_name

This works fine with both functions and methods :

In [1]: class A():
...:     @print_name()
...:     def a():
...:         print('Hi from A.a')
In [2]: A.a()
    __main__.A.a
    Hi from A.a

In [25]: @print_name()
    ...: def b():
    ...:     print('Hi from b')
    ...: 
In [26]: b()
    __main__.b
    Hi from b
like image 161
SEDaradji Avatar answered Oct 18 '22 10:10

SEDaradji