Interest Ask. This is how I do it.
(This works in python2. I have not tested it in python3, but I will not be surprised if it does not work ...)
You can iterate over all the “nominees” with the help reversed(inspect.getmro(cls))and return the first (by extracting the value of the nextiterator) that satisfy the condition that it has the corresponding attrone and that attrmatches the method of the corresponding one cls.
im_func .
import inspect
def getMethodClass(cls, attr):
return next(
basecls for basecls in reversed(inspect.getmro(cls))
if hasattr(basecls, attr)
and getattr(basecls, attr).im_func is getattr(cls, attr).im_func
)
getMethodClass(A, 'a')
=> __main__.A
getMethodClass(B, 'a')
=> __main__.A
getMethodClass(B, 'b')
=> __main__.B
# an alternative implementation, suggested by @chameleon
def getAttributeClass(cls, attrName):
# check first if has attribute
attr = getattr(cls, attrName)
mro = inspect.getmro(cls)
# only one class on list
if len(mro) == 1:
return cls
# many class on list
for base in reversed(mro[1:]):
# check if defined in this base
try:
baseAttr = getattr(base, attrName)
except AttributeError:
continue
else:
if baseAttr.im_func is attr.im_func:
return base
# define in top class
return cls
, :
def getMethodClass(unbound_method):
cls = unbound_method.im_class
attr = unbound_method.__name__
getMethodClass(B.a)
=> __main__.A