Al llamar a un método anulado, superclase y método anulado a las llamadas

Este código lanza una excepción, AttributeError, “wtf!” , porque A.foo() está llamando a B.foo1() , ¿no debería llamar a A.foo1() ? ¿Cómo puedo obligarlo a llamar a A.foo1() (y cualquier método llamado dentro de A.foo() debería llamar a A.* )

 class A(object): def foo(self): print self.foo1() def foo1(self): return "foo" class B(A): def foo1(self): raise AttributeError, "wtf!" def foo(self): raise AttributeError, "wtf!" def foo2(self): super(B, self).foo() myB = B() myB.foo2() 

En la clase A, en lugar de llamar a los métodos self , es necesario llamar a los métodos A y pasarlos de self manual.

Esta no es la forma normal de hacer las cosas, debe tener una buena razón para hacerlo así.

 class A(object): def foo(self): print A.foo1(self) def foo1(self): return "foo" class B(A): def foo1(self): raise AttributeError, "wtf!" def foo(self): raise AttributeError, "wtf!" def foo2(self): super(B, self).foo() myB = B() myB.foo2() 

Funciona según lo previsto, como funciona el 100% de los lenguajes de progtwigción mundiales. La subclase anula TODOS los métodos de la clase padre.

Sin embargo, si realmente quieres llamar a A.foo1 () puedes hacerlo así (no puedo garantizarlo). Y en cualquier caso, no debe hacer esto, ya que esto va en contra de todos los principios de una buena progtwigción.

  class A(object): def foo(self): A.foo1(self) 

En el código:

 def foo2(self): super(B, self).foo() 

el yo es un ejemplo de B.

Cuando se llama a un método derivado de A por una instancia de B, comenzará a buscar en el espacio de nombres de B, y solo si no se encuentra el método (por ejemplo, B no reemplaza) se usa la implementación de A, pero siempre con self refiriéndose a B. En ningún momento el yo es un ejemplo de A.

Uno puede ver lo que Python está haciendo aquí, pero la forma de anular es un poco extrema. Tome el caso cuando la clase A define 100 atributos y la clase B los hereda y agregue 1 atributo más. Queremos poder tener __init __ () para B, llamar a __init __ () para A y dejar que el código de B defina solo su único atributo. De manera similar, si definimos un método reset () en A para establecer todos los atributos en cero, entonces el método reset () correspondiente para B debería poder llamar al método reset () para A y luego poner a cero el único atributo B en su lugar. de tener que duplicar todo el código de A. Python está dificultando lo que se supone que es una gran ventaja de la progtwigción orientada a objetos; Es decir, la reutilización del código. La mejor opción aquí es evitar anular los métodos que realmente queremos reutilizar. Si quieres tener una idea de las complicaciones con Python aquí, prueba este código:

 class X(object): def __init__ ( self ): print "X" self.x = 'x' self.reset() print "back to X" def reset ( self ): print "reset X" self.xx = 'xx' class Y(X): def __init__ ( self ): print "Y" super(Y,self).__init__() self.y = 'y' self.reset() print "back to Y" def reset ( self ): print "reset Y" super(Y,self).reset() print "back to reset Y" self.yy = 'yy' aY = Y() 

(Para que esto funcione correctamente, elimine la llamada self.reset () en __init __ () para la clase Y).