1

我有两节课:

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
4

1 回答 1

1

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

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

您可以使用 迭代所有“被提名人” reversed(inspect.getmro(cls)),并返回next满足其具有相关条件的第一个(通过获取迭代器的值),这与相关attrattr方法相同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
于 2014-04-06T19:19:00.837 回答