We can use method resolution order or mro() to find the name of SomeClass from some_method it has:
class SomeClass: def __init__(self): self.foo = 100 def some_method(self): return self.foo a = SomeClass() print(a.some_method.__self__.__class__.mro()[0])
Outputs:
<class '__main__.SomeClass'>
that way we can find the name of the class that some_method belongs to even if it's inherited by SomeOtherClass:
class SomeClass: def __init__(self): self.foo = 100 def some_method(self): return self.foo class SomeOtherClass(SomeClass): def __init__(self): super().__init__() self.other_foo = 1 def some_other_method(self): return self.other_foo a = SomeOtherClass() print([cls for cls in a.some_method.__self__.__class__.mro() if cls.__dict__.__contains__(a.some_method.__name__)][0]) print([cls for cls in a.some_other_method.__self__.__class__.mro() if cls.__dict__.__contains__(a.some_other_method.__name__)][0])
Outputs:
<class '__main__.SomeClass'> <class '__main__.SomeOtherClass'>
or the names of all the classes that have some_method (or some_other_method):
print([cls for cls in a.some_method.__self__.__class__.mro() if hasattr(cls, a.some_method.__name__)]) print([cls for cls in a.some_other_method.__self__.__class__.mro() if hasattr(cls, a.some_other_method.__name__)])
Outputs:
[<class '__main__.SomeOtherClass'>, <class '__main__.SomeClass'>] [<class '__main__.SomeOtherClass'>]
To get the __name__s in string:
print([cls.__name__ ...