2009-11-21 6 views
6

Aquí es mi conjetura, que no funciona:¿Cómo puede una clase base de Python decir si una subclase ha anulado sus métodos?

class BaseClass(object): 
    def foo(self): 
     return 'foo' 
    def bar(self): 
     return 'bar' 
    def methods_implemented(self): 
     """This doesn't work...""" 
     overriden = [] 
     for method in ('foo', 'bar'): 
      this_method = getattr(self, method) 
      base_method = getattr(BaseClass, method) 
      if this_method is not base_method: 
       overriden.append(method) 
     return overriden 

class SubClass(BaseClass): 
    def foo(self): 
     return 'override foo' 

o = SubClass() 
o.methods_implemented() 

Idealmente, methods_implemented() devolvería [ 'foo'].

¿Cómo?

(¿Por qué querría hacer esto? Mi clase base es una clase de recursos HTTP que tiene métodos GET, POST, etc. Por defecto, devuelven 405 Method Not Implemented. También tiene un método OPTIONS que debería devolver 200 respuestas con el encabezado Permitir establecer los métodos que implemente cualquier subclase.)

+4

¿Por qué es esto una wiki de la comunidad? –

+5

No estoy seguro de por qué querría hacer esto. En cualquier jerarquía de clases, no se debe exigir a una clase base que sepa algo sobre las clases derivadas. Si esto es necesario, ** tal vez ** su diseño debe ser reconsiderado. – Steg

+4

Acepto que esto no debería ser wiki: habrá una respuesta que funcione y pueda ser aceptada. Además, me gustaría saber más acerca de por qué quieres hacer esto, no porque no debas, sino porque parece una de esas soluciones a un problema que tiene una solución mejor y más diferente en otro lugar. –

Respuesta

9

¿Quizás esto?

>>> class BaseClass(object): 
...  def foo(self): 
...   return 'foo' 
...  def bar(self): 
...   return 'bar' 
...  def methods_implemented(self): 
...   """This does work.""" 
...   overriden = [] 
...   for method in ('foo', 'bar'): 
...    this_method = getattr(self, method) 
...    base_method = getattr(BaseClass, method) 
...    if this_method.__func__ is not base_method.__func__: 
...     overriden.append(method) 
...   return overriden 
... 
>>> class SubClass(BaseClass): 
...  def foo(self): 
...   return 'override foo' 
... 
>>> o = SubClass() 
>>> o.methods_implemented() 
['foo'] 

Esto comprueba si los objetos de función detrás de los métodos vinculados son los mismos.

Nota: antes de Python 2.6, el atributo __func__ se llamaba im_func.

+0

Esto funciona, con la excepción de que en mi intérprete de python-2.5 necesita comprobar im_func, no __func__. Tal vez podrías mencionar eso en tu respuesta. Gracias. – Tenac

+1

De nada, aunque la próxima vez consideraría no marcar preguntas como esta como 'community wiki'. ¡A los respondedores les gusta obtener sus puntos! –

0

Los métodos, aunque llaman al mismo objeto, NO son el mismo objeto. Debe probar para ver si las funciones envueltas en el método independiente son el mismo objeto.

Estoy usando 2.6 aquí, así que también cambié la clase para heredar del objeto.

>>> class BaseClass(object): 
...  def foo(self): 
...   return 'foo' 
...  def bar(self): 
...   return 'bar' 
...  def methods_implemented(self): 
...   """This doesn't work...""" 
...   overriden = [] 
...   for method in ('foo', 'bar'): 
...    this_method = getattr(self, method).__func__ 
...    base_method = getattr(BaseClass, method).__func__ 
...    if this_method is base_method: 
...     overriden.append(method) 
...   return overriden 
... 
>>> class SubClass(BaseClass): 
...  def foo(self): 
...   return 'override foo' 
... 
>>> o = SubClass() 
>>> o.methods_implemented() 
['bar'] 
Cuestiones relacionadas