How to get class name from class method?

Viewed 438

Please check the simple code below:

def extract_class_from_func(func_var):
    # should return class of the func_var
    return ...

class A:
     def m(self):
         print(self, "m")

func_var = A.m

# This check should succeed
assert A == extract_class_from_func(func_var)

Please help me in implementing method extract_class_from_func

3 Answers

You can't. In Python 2, this reference was available at A.m.im_class. But, to quote from PEP 3155 - Qualified name for classes and functions:

This possibility is gone in Python 3.

There is no longer any such thing as an "unbound method" and the function A.m is no different from a regular function - it does not hold any reference to the class object. In fact, you can even delete the class and see the "method" still works:

>>> class Ameta(type):
...     def __del__(self):
...         print("goodbye A")
... 
>>> class A(metaclass=Ameta):
...     def m(self):
...         print(self, "m")
... 
>>> f = A.m
>>> import gc
>>> del A
>>> gc.collect()
goodbye A
6
>>> f("")
 m

However, the PEP did provide some limited support for what you wanted: if you look in A.m.__qualname__ you will find a string from which you may be able to introspect the class A.

The module can be found using func_var.__module__ and class name can be found using __qualname__. Then you just perform string import as below:

import importlib    
def extract_class_from_func(func_var):
        className = func_var.__qualname__.split('.')[0]
        return getattr(importlib.import_module(func_var.__module__), className)



class Greet:
    def __init__(self):
        pass
    def sayHi(self):
        print("Hi!")


>>> Greet == extract_class_from_func(Greet.sayHi)
>>> True

You can do like this.

def extract_class_from_func(func_var):
    return func_var.__qualname__.split('.')[0]
Related