如何检查Python从哪个类方法派生?

时间:2014-04-06 18:21:18

标签: python introspection method-resolution-order

我有两个班级:

class A(object):
  def a(self):
    pass

class B(A):
  def b(self):
    pass

print dir(A)
print dir(B)

如何检查Python中派生的类方法?

例如:

getMethodClass(A.a) == A
getMethodClass(B.a) == A
getMethodClass(B.b) == B

1 个答案:

答案 0 :(得分:1)

有趣的问题。我就是这样做的。

(这在python2中有效。我没有在python3中测试它,但如果它不起作用我也不会感到惊讶......)

您可以使用reversed(inspect.getmro(cls))遍历所有“提名者”,并返回第一个(通过获取迭代器的next值),该值满足条件attr } attr与相关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__
    # rest of implementation is the same as before...

getMethodClass(B.a)
=> __main__.A