How to get class name from class method? - python

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

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

How do I get the class which the function belongs to? [duplicate]

How can I get the class that defined a method in Python?
I'd 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)
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
I don't know why no one has ever brought this up or why the top answer has 50 upvotes when it is slow as 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 changed and you'll need to look into .__qualname__.
In Python 3, if you need the actual 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 could belong to a nested class you would 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
Thanks Sr2222 for pointing out I was missing the point...
Here's the corrected approach which is just like Alex's but does not require to import anything. I don't think it's an improvement though, unless there's a huge hierarchy of inherited classes as this approach stops as soon as the defining class is found, instead of returning the whole inheritance as getmro does. As said, this is a very 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 the 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 solution returns the same results. As long as Alex approach can be used, I would use it instead of this one.
Python 3
Solved it in a very simple way:
str(bar.foo_method).split(" ", 3)[-2]
This gives
'FooClass.foo_method'
Split on the dot to get the class and the function name separately
I found __qualname__ is useful in Python3.
I test it like that:
class Cls(object):
def func(self):
print('1')
c = Cls()
print(c.func.__qualname__)
# output is: 'Cls.func'
def single_func():
print(2)
print(single_func.__module__)
# output: '__main__'
print(single_func.__qualname__)
# output: 'single_func'
After my test, I found another answer here.
I started doing something somewhat similar, basically the idea was checking whenever a method in a base class had been implemented or not in a sub class. Turned out the way I originally did it I could not detect when an intermediate class was actually implementing the method.
My workaround for it was quite simple actually; setting a method attribute and testing its presence later. Here's an simplification of the whole thing:
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() (isn't that the spirit?) and have it pass all arguments unmodified to the method.
P.S.: This answer does not directly answer the question. IMHO there are two reasons one would want to know which class defined a method; first is to point fingers at a class in debug code (such as in exception handling), and the second is to determine if the method has been re-implemented (where method is a stub meant to be implemented by the programmer). This answer solves that second case in a different way.
if you get this error:
'function' object has no attribute 'im_class'
try this:
import inspect
def get_class_that_defined_method(meth):
class_func_defided = meth.__globals__[meth.__qualname__.split('.')[0]]
#full_func_name = "%s.%s.%s"%(class_func_defided.__module__,class_func_defided.__name__,meth.__name__)
if inspect.isfunction(class_func_defided):
print("%s is not part of a class."%meth.__name__)
return None
return class_func_defided
sample test:
class ExampleClass:
#staticmethod
def ex_static_method():
print("hello from static method")
def ex_instance_method(self):
print("hello from instance method")
def ex_funct(self):
print("hello from simple function")
if __name__ == "__main__":
static_method_class = get_class_that_defined_method(ExampleClass.ex_static_method)
static_method_class.ex_static_method()
instance_method_class = get_class_that_defined_method(ExampleClass.ex_instance_method)
instance_method_class().ex_instance_method()
function_class = get_class_that_defined_method(ex_funct)

how to get the class name of a statics method belongs to it [duplicate]

How can I get the class that defined a method in Python?
I'd 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)
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
I don't know why no one has ever brought this up or why the top answer has 50 upvotes when it is slow as 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 changed and you'll need to look into .__qualname__.
In Python 3, if you need the actual 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 could belong to a nested class you would 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
Thanks Sr2222 for pointing out I was missing the point...
Here's the corrected approach which is just like Alex's but does not require to import anything. I don't think it's an improvement though, unless there's a huge hierarchy of inherited classes as this approach stops as soon as the defining class is found, instead of returning the whole inheritance as getmro does. As said, this is a very 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 the 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 solution returns the same results. As long as Alex approach can be used, I would use it instead of this one.
Python 3
Solved it in a very simple way:
str(bar.foo_method).split(" ", 3)[-2]
This gives
'FooClass.foo_method'
Split on the dot to get the class and the function name separately
I found __qualname__ is useful in Python3.
I test it like that:
class Cls(object):
def func(self):
print('1')
c = Cls()
print(c.func.__qualname__)
# output is: 'Cls.func'
def single_func():
print(2)
print(single_func.__module__)
# output: '__main__'
print(single_func.__qualname__)
# output: 'single_func'
After my test, I found another answer here.
I started doing something somewhat similar, basically the idea was checking whenever a method in a base class had been implemented or not in a sub class. Turned out the way I originally did it I could not detect when an intermediate class was actually implementing the method.
My workaround for it was quite simple actually; setting a method attribute and testing its presence later. Here's an simplification of the whole thing:
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() (isn't that the spirit?) and have it pass all arguments unmodified to the method.
P.S.: This answer does not directly answer the question. IMHO there are two reasons one would want to know which class defined a method; first is to point fingers at a class in debug code (such as in exception handling), and the second is to determine if the method has been re-implemented (where method is a stub meant to be implemented by the programmer). This answer solves that second case in a different way.
if you get this error:
'function' object has no attribute 'im_class'
try this:
import inspect
def get_class_that_defined_method(meth):
class_func_defided = meth.__globals__[meth.__qualname__.split('.')[0]]
#full_func_name = "%s.%s.%s"%(class_func_defided.__module__,class_func_defided.__name__,meth.__name__)
if inspect.isfunction(class_func_defided):
print("%s is not part of a class."%meth.__name__)
return None
return class_func_defided
sample test:
class ExampleClass:
#staticmethod
def ex_static_method():
print("hello from static method")
def ex_instance_method(self):
print("hello from instance method")
def ex_funct(self):
print("hello from simple function")
if __name__ == "__main__":
static_method_class = get_class_that_defined_method(ExampleClass.ex_static_method)
static_method_class.ex_static_method()
instance_method_class = get_class_that_defined_method(ExampleClass.ex_instance_method)
instance_method_class().ex_instance_method()
function_class = get_class_that_defined_method(ex_funct)

Get name of current class?

How do I get the name of the class I am currently in?
Example:
def get_input(class_name):
[do things]
return class_name_result
class foo():
input = get_input([class name goes here])
Due to the nature of the program I am interfacing with (vistrails), I cannot use __init__() to initialize input.
obj.__class__.__name__ will get you any objects name, so you can do this:
class Clazz():
def getName(self):
return self.__class__.__name__
Usage:
>>> c = Clazz()
>>> c.getName()
'Clazz'
Within the body of a class, the class name isn't defined yet, so it is not available. Can you not simply type the name of the class? Maybe you need to say more about the problem so we can find a solution for you.
I would create a metaclass to do this work for you. It's invoked at class creation time (conceptually at the very end of the class: block), and can manipulate the class being created. I haven't tested this:
class InputAssigningMetaclass(type):
def __new__(cls, name, bases, attrs):
cls.input = get_input(name)
return super(MyType, cls).__new__(cls, name, bases, newattrs)
class MyBaseFoo(object):
__metaclass__ = InputAssigningMetaclass
class foo(MyBaseFoo):
# etc, no need to create 'input'
class foo2(MyBaseFoo):
# etc, no need to create 'input'
PEP 3155 introduced __qualname__, which was implemented in Python 3.3.
For top-level functions and classes, the __qualname__ attribute is equal to the __name__ attribute. For nested classes, methods, and nested functions, the __qualname__ attribute contains a dotted path leading to the object from the module top-level.
It is accessible from within the very definition of a class or a function, so for instance:
class Foo:
print(__qualname__)
will effectively print Foo.
You'll get the fully qualified name (excluding the module's name), so you might want to split it on the . character.
However, there is no way to get an actual handle on the class being defined.
>>> class Foo:
... print('Foo' in globals())
...
False
You can access it by the class' private attributes:
cls_name = self.__class__.__name__
EDIT:
As said by Ned Batchelder, this wouldn't work in the class body, but it would in a method.
EDIT: Yes, you can; but you have to cheat: The currently running class name is present on the call stack, and the traceback module allows you to access the stack.
>>> import traceback
>>> def get_input(class_name):
... return class_name.encode('rot13')
...
>>> class foo(object):
... _name = traceback.extract_stack()[-1][2]
... input = get_input(_name)
...
>>>
>>> foo.input
'sbb'
However, I wouldn't do this; My original answer is still my own preference as a solution. Original answer:
probably the very simplest solution is to use a decorator, which is similar to Ned's answer involving metaclasses, but less powerful (decorators are capable of black magic, but metaclasses are capable of ancient, occult black magic)
>>> def get_input(class_name):
... return class_name.encode('rot13')
...
>>> def inputize(cls):
... cls.input = get_input(cls.__name__)
... return cls
...
>>> #inputize
... class foo(object):
... pass
...
>>> foo.input
'sbb'
>>>
#Yuval Adam answer using #property
class Foo():
#property
def name(self):
return self.__class__.__name__
f = Foo()
f.name # will give 'Foo'
I think, it should be like this:
class foo():
input = get_input(__qualname__)
import sys
def class_meta(frame):
class_context = '__module__' in frame.f_locals
assert class_context, 'Frame is not a class context'
module_name = frame.f_locals['__module__']
class_name = frame.f_code.co_name
return module_name, class_name
def print_class_path():
print('%s.%s' % class_meta(sys._getframe(1)))
class MyClass(object):
print_class_path()
I'm using python3.8 and below is example to get your current class name.
class MyObject():
#classmethod
def print_class_name(self):
print(self.__name__)
MyObject.print_class_name()
Or without #classmethod you can use
class ClassA():
def sayhello(self):
print(self.getName())
def getName(self):
return self.__class__.__name__
ClassA().sayhello()
Hope that helps others !!!

Mocking out methods on any instance of a python class

I want to mock out methods on any instance of some class in the production code in order to facilitate testing. Is there any library in Python which could facilitate this?
Basically, I want to do the following, but in Python (the following code is Ruby, using the Mocha library):
def test_stubbing_an_instance_method_on_all_instances_of_a_class
Product.any_instance.stubs(:name).returns('stubbed_name')
assert_equal 'stubbed_name', SomeClassThatUsesProduct.get_new_product_name
end
The important thing to note from above is that I need to mock it out on the class level, since I'm actually need to mock out methods on an instance created by the thing I'm testing.
Use Case:
I have a class QueryMaker which calls a method on an instance of RemoteAPI. I want to mock out the RemoteAPI.get_data_from_remote_server method to return some constant. How do I do this inside a test without having to put a special case within the RemoteAPI code to check for what environment it's running in.
Example of what I wanted in action:
# a.py
class A(object):
def foo(self):
return "A's foo"
# b.py
from a import A
class B(object):
def bar(self):
x = A()
return x.foo()
# test.py
from a import A
from b import B
def new_foo(self):
return "New foo"
A.foo = new_foo
y = B()
if y.bar() == "New foo":
print "Success!"
Needing to mock out methods when testing is very common and there are lots of tools to help you with it in Python. The danger with "monkey patching" classes like this is that if you don't undo it afterwards then the class has been modified for all other uses throughout your tests.
My library mock, which is one of the most popular Python mocking libraries, includes a helper called "patch" that helps you to safely patch methods or attributes on objects and classes during your tests.
The mock module is available from:
http://pypi.python.org/pypi/mock
The patch decorator can be used as a context manager or as a test decorator. You can either use it to patch out with functions yourself, or use it to automatically patch with Mock objects that are very configurable.
from a import A
from b import B
from mock import patch
def new_foo(self):
return "New foo"
with patch.object(A, 'foo', new_foo):
y = B()
if y.bar() == "New foo":
print "Success!"
This handles the unpatching for you automatically. You could get away without defining the mock function yourself:
from mock import patch
with patch.object(A, 'foo') as mock_foo:
mock_foo.return_value = "New Foo"
y = B()
if y.bar() == "New foo":
print "Success!"
Mock is the way to do it, alright.
It can be a bit tricky to make sure you're patching the instance method on any instances created from the class.
# a.py
class A(object):
def foo(self):
return "A's foo"
# b.py
from a import A
class B(object):
def bar(self):
x = A()
return x.foo()
# test.py
from a import A
from b import B
import mock
mocked_a_class = mock.Mock()
mocked_a_instance = mocked_a_class.return_value
mocked_a_instance.foo.return_value = 'New foo'
with mock.patch('b.A', mocked_a_class): # Note b.A not a.A
y = B()
if y.bar() == "New foo":
print "Success!"
Referenced in the docs, at the para starting "To configure return values on methods of instances on the patched class..."
Easiest way is probably to use a class method. You really should use an instance method, but it's a pain to create those, whereas there's a built-in function that creates a class method. With a class method, your stub will get a reference to the class (rather than the instance) as the first argument, but since it's a stub this probably doesn't matter. So:
Product.name = classmethod(lambda cls: "stubbed_name")
Note that the signature of the lambda must match the signature of the method you're replacing. Also, of course, since Python (like Ruby) is a dynamic language, there is no guarantee that someone won't switch out your stubbed method for something else before you get your hands on the instance, though I expect you will know pretty quickly if that happens.
Edit: On further investigation, you can leave out the classmethod():
Product.name = lambda self: "stubbed_name"
I was trying to preserve the original method's behavior as closely as possible, but it looks like it's not actually necessary (and doesn't preserve the behavior as I'd hoped, anyhow).
I don't know Ruby quite well enough to tell exactly what you're trying to do, but check out the __getattr__ method. If you define it in your class, Python will call it when code tries to access any attribute of your class that isn't otherwise defined. Since you want it to be a method, it will need to create a method on the fly that it returns.
>>> class Product:
... def __init__(self, number):
... self.number = number
... def get_number(self):
... print "My number is %d" % self.number
... def __getattr__(self, attr_name):
... return lambda:"stubbed_"+attr_name
...
>>> p = Product(172)
>>> p.number
172
>>> p.name()
'stubbed_name'
>>> p.get_number()
My number is 172
>>> p.other_method()
'stubbed_other_method'
Also note that __getattr__ needs to not use any other undefined attributes of your class, or else it will be infinitely recursive, calling __getattr__ for the attribute that doesn't exist.
... def __getattr__(self, attr_name):
... return self.x
>>> p.y
Traceback (most recent call last):
#clipped
RuntimeError: maximum recursion depth exceeded while calling a Python object
If this is something you only want to do from your test code, not the production code, then put your normal class definition in the production code file, then in the test code define the __getattr__ method (unbound), and then bind it to the class you want:
#production code
>>> class Product:
... def __init__(self, number):
... self.number = number
... def get_number(self):
... print "My number is %d" % self.number
...
#test code
>>> def __getattr__(self, attr):
... return lambda:"stubbed_"+attr_name
...
>>> p = Product(172)
>>> p.number
172
>>> p.name()
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: Product instance has no attribute 'name'
>>> Product.__getattr__ = __getattr__
>>> p.name()
'stubbed_name'
I'm not sure how this would react with a class that was already using __getattribute__ (as opposed to __getattr__, __getattribute__ is called for all attributes whether or not they exist).
If you only want to do this for specific methods that already exist, then you could do something like:
#production code
>>> class Product:
... def __init__(self, number):
... self.number = number
... def get_number(self):
... return self.number
...
>>> p = Product(172)
>>> p.get_number()
172
#test code
>>> def get_number(self):
... return "stub_get_number"
...
>>> Product.get_number = get_number
>>> p.get_number()
'stub_get_number'
Or if you really wanted to be elegant, you could create a wrapper function to make doing multiple methods easy:
#test code
>>> import functools
>>> def stubber(fn):
... return functools.wraps(fn)(lambda self:"stub_"+fn.__name__)
...
>>> Product.get_number = stubber(Product.get_number)
>>> p.get_number()
'stub_get_number'
#Orignal Class definition - path "module.Product"
class Product:
def method_A(self):
# do something
pass
def method_B(self):
self.random_attr = 1
#Test case
from module import Product
class MockedProduct(Product):
def method_B(self):
self.random_attr = 2
with mock.patch('module.Product', new=MockedProduct):
#Write test case logic here
#Now method_B function call on product class instance should return 2
#instead of 1
minimal reproducible example using pytest and monkeypatch
# a.py
class A(object):
def foo(self):
return "A's foo"
# b.py
from a import A
class B(object):
def bar(self):
x = A()
return x.foo()
# test_ab.py
import pytest
from a import A
from b import B
def new_foo(self):
return "New foo"
def test_mock_instance_method(monkeypatch):
y = B()
print(y.bar())
monkeypatch.setattr(A, 'foo', new_foo)
print(y.bar())
gives you
$ pytest -rP .
============================= test session starts ==============================
platform linux -- Python 3.8.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /home/user/220225so
plugins: cov-3.0.0
collected 1 item
test_ab.py . [100%]
==================================== PASSES ====================================
__________________________ test_mock_instance_method ___________________________
----------------------------- Captured stdout call -----------------------------
A's foo
New foo
============================== 1 passed in 0.01s ===============================
$

Get class that defined method

How can I get the class that defined a method in Python?
I'd 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)
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
I don't know why no one has ever brought this up or why the top answer has 50 upvotes when it is slow as 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 changed and you'll need to look into .__qualname__.
In Python 3, if you need the actual 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 could belong to a nested class you would 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
Thanks Sr2222 for pointing out I was missing the point...
Here's the corrected approach which is just like Alex's but does not require to import anything. I don't think it's an improvement though, unless there's a huge hierarchy of inherited classes as this approach stops as soon as the defining class is found, instead of returning the whole inheritance as getmro does. As said, this is a very 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 the 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 solution returns the same results. As long as Alex approach can be used, I would use it instead of this one.
Python 3
Solved it in a very simple way:
str(bar.foo_method).split(" ", 3)[-2]
This gives
'FooClass.foo_method'
Split on the dot to get the class and the function name separately
I found __qualname__ is useful in Python3.
I test it like that:
class Cls(object):
def func(self):
print('1')
c = Cls()
print(c.func.__qualname__)
# output is: 'Cls.func'
def single_func():
print(2)
print(single_func.__module__)
# output: '__main__'
print(single_func.__qualname__)
# output: 'single_func'
After my test, I found another answer here.
I started doing something somewhat similar, basically the idea was checking whenever a method in a base class had been implemented or not in a sub class. Turned out the way I originally did it I could not detect when an intermediate class was actually implementing the method.
My workaround for it was quite simple actually; setting a method attribute and testing its presence later. Here's an simplification of the whole thing:
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() (isn't that the spirit?) and have it pass all arguments unmodified to the method.
P.S.: This answer does not directly answer the question. IMHO there are two reasons one would want to know which class defined a method; first is to point fingers at a class in debug code (such as in exception handling), and the second is to determine if the method has been re-implemented (where method is a stub meant to be implemented by the programmer). This answer solves that second case in a different way.
if you get this error:
'function' object has no attribute 'im_class'
try this:
import inspect
def get_class_that_defined_method(meth):
class_func_defided = meth.__globals__[meth.__qualname__.split('.')[0]]
#full_func_name = "%s.%s.%s"%(class_func_defided.__module__,class_func_defided.__name__,meth.__name__)
if inspect.isfunction(class_func_defided):
print("%s is not part of a class."%meth.__name__)
return None
return class_func_defided
sample test:
class ExampleClass:
#staticmethod
def ex_static_method():
print("hello from static method")
def ex_instance_method(self):
print("hello from instance method")
def ex_funct(self):
print("hello from simple function")
if __name__ == "__main__":
static_method_class = get_class_that_defined_method(ExampleClass.ex_static_method)
static_method_class.ex_static_method()
instance_method_class = get_class_that_defined_method(ExampleClass.ex_instance_method)
instance_method_class().ex_instance_method()
function_class = get_class_that_defined_method(ex_funct)

Categories

Resources