有没有办法在Python中识别继承的方法?

有没有办法在Python中识别继承的方法?,python,inheritance,Python,Inheritance,我想将继承的方法与重载或新定义的方法区分开来。Python能做到这一点吗 例如: class A(object): def spam(self): print 'A spam' def ham(self): print 'A ham' class B(A): def spam(self): print 'Overloaded spam' def eggs(self): print 'Newly defined eggs' 所需功能: >&

我想将继承的方法与重载或新定义的方法区分开来。Python能做到这一点吗

例如:

class A(object):
  def spam(self):
    print 'A spam'
  def ham(self):
    print 'A ham'

class B(A):
  def spam(self):
    print 'Overloaded spam'
  def eggs(self):
    print 'Newly defined eggs'
所需功能:

>>> magicmethod(B.spam)
'overloaded'
>>> magicmethod(B.ham)
'inherited'
>>> magicmethod(B.eggs)
'newly defined'

有没有像示例中那样的“神奇方法”,或者有什么方法可以区分这些类型的方法实现?

如果您知道祖先,您可以简单地测试:

>>> B.spam == A.spam
False
>>> B.ham == A.ham
True
要查找所有基类的列表,请查看以下内容:


我还要指出,如果你需要这个,你的类设计可能是错误的。在OOP中,您不应该关心这些事情(除非您正在创建对象检查器或类似的东西)。

我不确定这是一个好主意,但您可能可以使用
hasattr
\u dict\u
来完成

def magicmethod(clazz, method):
    if method not in clazz.__dict__:  # Not defined in clazz : inherited
        return 'inherited'
    elif hasattr(super(clazz), method):  # Present in parent : overloaded
        return 'overloaded'
    else:  # Not present in parent : newly defined
        return 'newly defined'

扩展了hamstergene的答案;类将其基类存储在类变量

def magicmethod(clazz, method):
    if method not in clazz.__dict__:  # Not defined in clazz : inherited
        return 'inherited'
    elif hasattr(super(clazz), method):  # Present in parent : overloaded
        return 'overloaded'
    else:  # Not present in parent : newly defined
        return 'newly defined'
因此:

>>B.spam==B.\uuuu基\uuuu[0]。spam
假的
>>>B.ham==B.。\uuuuu基[0]。ham
真的
>>>B.eggs==B.。\uuuuu碱基\uuuuuu[0]。鸡蛋
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:类型对象“A”没有属性“eggs”
>>>hasattr(B,“蛋”)
真的
>>>hasattr(B.“碱基”[0],“蛋”)
假的
通常的方法是(python 2.*):


对于新样式的类,您有一个方法
mro()
,返回方法结果顺序列表<代码>[0]
是类本身

所以你可以

>>> any(hasattr(i, 'ham') for i in B.mro()[1:])
True
>>> any(hasattr(i, 'spam') for i in B.mro()[1:])
True
>>> any(hasattr(i, 'eggs') for i in B.mro()[1:])
False
因此,
egs
是新定义的

>>> any(getattr(B, 'ham') == getattr(i, 'ham', None) for i in B.mro()[1:])
True
>>> any(getattr(B, 'spam') == getattr(i, 'spam', None) for i in B.mro()[1:])
False
因此
ham
是继承的


有了这些,你就可以设计自己的启发式方法。

这在OOP中是一个奇怪的要求,这是一种特殊情况,在这种情况下,可能需要扩展对象而不需要子类化。我必须检查是否可以简单地重写其中一个方法,或者是否必须保留已存在的重写方法。是的,它在某种程度上是一个对象检查器,即使不是为了调试/分析目的。我意识到这可能并不总是一个好主意,但我认为在这种情况下,这是合理的。感谢您指出可能的设计错误。hasattr(super(clazz),method)仅适用于方法,因为super(clazz)为该类的方法返回一个代理类。e、 g.类属性不是代理类的一部分
>>> any(getattr(B, 'ham') == getattr(i, 'ham', None) for i in B.mro()[1:])
True
>>> any(getattr(B, 'spam') == getattr(i, 'spam', None) for i in B.mro()[1:])
False