2011-10-13 12 views
8

Quiero diferenciar los métodos heredados de los métodos sobrecargados o recientemente definidos. ¿Es eso posible con Python?¿Hay alguna manera de identificar un método heredado en Python?

Ejemplo:

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' 

funcionalidad deseada:

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

¿Hay un "método mágico", como en el ejemplo, o alguna forma de saber los tipos de implementaciones de métodos de separación?

Respuesta

12

No estoy seguro de que sea una buena idea, pero probablemente puede hacerlo usando hasattr y __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

Si conoce el ancestro, puede simplemente prueba:

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

Y para encontrar una lista de todas las clases de base, mira aquí: List all base classes in a hierarchy of given class?

Serán asimismo señalar que si necesita esto, su el diseño de clase probablemente sea incorrecto No debería preocuparse por tales cosas en OOP (a menos que esté creando un inspector de objetos o algo así).

+0

Buena llamada que este es un requisito extraño en OOP – Pengman

+0

Este es un caso especial, donde un objeto podría tener que ser extendido sin ser subclasificado. Tengo que comprobar si puedo simplemente anular uno de los métodos, o si tengo que preservar un método de anulación ya existente. Entonces, sí, es un inspector de objetos en cierto modo, aunque no con fines de depuración/análisis. Me doy cuenta de que esto no siempre es una buena idea, pero creo que en este caso está justificado. Gracias por señalar las posibles fallas de diseño. –

0

Expandiendo la respuesta de hamstergene; una clase almacena sus clases base en la variable de clase __bases__.

Así:

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

manera general habrá (pitón 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

Para las clases de nuevo estilo, que tiene un método mro(), volviendo la lista de métodos para resulution . [0] es la clase en sí.

Por lo que podría hacer

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

Así eggs se acaba de definir.

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

So ham es heredado.

Con estos, puede crear sus propias heurísticas.

Cuestiones relacionadas