Get the class that defined the method

How can I get the class that defined the method in Python?

I want the following example to print " __main__.FooClass ":

 class FooClass: def foo_method(self): print "foo" class BarClass(FooClass): pass bar = BarClass() print get_class_that_defined_method(bar.foo_method) 
+73
python python-datamodel
Jun 07 '09 at 2:18
source share
5 answers
 import inspect def get_class_that_defined_method(meth): for cls in inspect.getmro(meth.im_class): if meth.__name__ in cls.__dict__: return cls return None 
+62
Jun 07 '09 at 2:23
source share

Thanks to Sr2222 for not noticing the point ...

Here's an adjusted approach that is similar to Alex but does not require importing anything. I don’t think this is an improvement if there is no huge hierarchy of inherited classes, since this approach stops as soon as the defining class is defined, instead of returning the whole inheritance as getmro . As said, this is an unlikely scenario.

 def get_class_that_defined_method(method): method_name = method.__name__ if method.__self__: classes = [method.__self__.__class__] else: #unbound method classes = [method.im_class] while classes: c = classes.pop() if method_name in c.__dict__: return c else: classes = list(c.__bases__) + classes return None 

And an example:

 >>> class A(object): ... def test(self): pass >>> class B(A): pass >>> class C(B): pass >>> class D(A): ... def test(self): print 1 >>> class E(D,C): pass >>> get_class_that_defined_method(A().test) <class '__main__.A'> >>> get_class_that_defined_method(A.test) <class '__main__.A'> >>> get_class_that_defined_method(B.test) <class '__main__.A'> >>> get_class_that_defined_method(C.test) <class '__main__.A'> >>> get_class_that_defined_method(D.test) <class '__main__.D'> >>> get_class_that_defined_method(E().test) <class '__main__.D'> >>> get_class_that_defined_method(E.test) <class '__main__.D'> >>> E().test() 1 

Alex's solution returns the same results. While the Alex approach is used, I would use it instead.

+7
Nov 29
source share

I don’t know why no one ever talked about this or why the main answer has 50 priorities when it is slow, like hell, but you can also do the following:

 def get_class_that_defined_method(meth): return meth.im_class.__name__ 

For python 3, I believe this has changed, and you need to take a look at .__qualname__ .

+3
Oct 02 '17 at 21:09 on
source share

I started to do something similar, basically the idea was checked whenever the base class method was implemented or not in the subclass. It turned out how I originally did this, I could not detect when the intermediate class actually applied this method.

My workaround for this was pretty simple; attribute setting method and subsequent testing of its presence. Here's a simplification of everything:

 class A(): def method(self): pass method._orig = None # This attribute will be gone once the method is implemented def run_method(self, *args, **kwargs): if hasattr(self.method, '_orig'): raise Exception('method not implemented') self.method(*args, **kwargs) class B(A): pass class C(B): def method(self): pass class D(C): pass B().run_method() # ==> Raises Exception: method not implemented C().run_method() # OK D().run_method() # OK 

UPDATE: Actually call method() from run_method() (right?) And pass all arguments that are not modified for the method.

PS: This answer does not directly answer the question. IMHO there are two reasons that I would like to know which class defined the method; First, you should point your fingers at the class in the debugging code (for example, in exception handling), and the second should determine if the method has been re-implemented (where the method is a stub intended for implementation by the programmer). This answer solves this second case differently.

+1
Oct. 15 '14 at 20:44
source share

In Python 3, if you need a real class object, you can do:

 import sys f = Foo.my_function vars(sys.modules[f.__module__])[f.__qualname__.split('.')[0]] # Gets Foo object 

If the function may belong to a nested class, you need to iterate as follows:

 f = Foo.Bar.my_function vals = vars(sys.modules[f.__module__]) for attr in f.__qualname__.split('.')[:-1]: vals = vals[attr] # vals is now the class Foo.Bar 
0
Apr 19 '19 at 19:43
source share



All Articles