2011-10-13 193 views
8

我想告诉除了重载或新定义的方法之外的继承方法。这可能与Python?有没有办法在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' 

是否有“魔术方法”像在本例中,或一些方式告诉那些类型的方法实现开的?

回答

12

我不确定这是个好主意,但您可以使用hasattr__dict__来做到这一点。

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' 
7

如果你知道的祖先,你可以简单的测试:

>>> B.spam == A.spam 
False 
>>> B.ham == A.ham 
True 

,并找到所有的基类的列表,看看这里:List all base classes in a hierarchy of given class?

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

+0

好的呼叫,这是一个奇怪的要求在OOP – Pengman

+0

这是一个特殊的情况下,一个对象可能不得不被扩展的子类。我必须检查我是否可以简单地重写其中一种方法,或者是否必须保留现有的重写方法。所以是的,尽管不是用于调试/分析的目的,它仍然是一种对象检查器。 我意识到这可能并不总是一个好主意,但我认为在这种情况下是合理的。感谢您指出可能的设计缺陷。 –

0

扩展在hamstergene的答案;一个类将其基类存储在类变量__bases__中。

所以:

>>> B.spam == B.__bases__[0].spam 
False 
>>> B.ham == B.__bases__[0].ham 
True 
>>> B.eggs == B.__bases__[0].eggs 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: type object 'A' has no attribute 'eggs' 
>>> hasattr(B,"eggs") 
True 
>>> hasattr(B.__bases__[0],"eggs") 
False 
6

一般的方式将是(蟒蛇2 *):

def _getclass(method): 
    try: 
     return method.im_class 
    except AttributeError: 
     return method.__class__ 

def magicmethod(method): 
    method_cls = _getclass(method) 
    if method.__name__ not in method_cls.__dict__: 
     return 'inherited' 
    for cls in method_cls.__mro__[1:]: 
     if method.__name__ in cls.__dict__: 
      return 'overloaded' 
    return 'newly defined' 


__test__ = {"example": """ 

    >>> 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' 
    >>> magicmethod(B.__init__) 
    'inherited' 
"""} 
0

对于新样式类,你有一个方法mro(),返回的方法resulution顺序列表。 [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 

所以eggs被重新定义。

>>> 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被继承。

有了这些,你可以制定自己的启发式。

相关问题