programming oriented opp exercises español and python oop

python - oriented - ¿Cuándo usar ''raise NotImplementedError''?



python oop exercises (4)

¿Es para recordarse a usted mismo y a su equipo para implementar la clase correctamente? No entiendo completamente el uso de una clase abstracta como esta:

class RectangularRoom(object): def __init__(self, width, height): raise NotImplementedError def cleanTileAtPosition(self, pos): raise NotImplementedError def isTileCleaned(self, m, n): raise NotImplementedError


Como dice Uriel , está destinado a un método en una clase abstracta que debe implementarse en una clase secundaria, pero también puede usarse para indicar un TODO.

Hay una alternativa para el primer caso de uso: clases base abstractas . Los que ayudan a crear clases abstractas.

Aquí hay un ejemplo de Python 3:

class C(abc.ABC): @abstractmethod def my_abstract_method(self, ...): ...

Al crear una instancia de C , obtendrá un error porque my_abstract_method es abstracto. Necesitas implementarlo en una clase infantil.

TypeError: Can''t instantiate abstract class C with abstract methods my_abstract_method

Subclase C e implementa my_abstract_method .

class D(C): def my_abstract_method(self, ...): ...

Ahora puedes instanciar D

C.my_abstract_method no tiene que estar vacío. Se puede llamar desde D usando super() .

Una ventaja de esto sobre NotImplementedError es que obtiene una Exception explícita en el momento de la NotImplementedError instancias, no en el tiempo de llamada de método.


Como indica la documentación [docs] ,

En las clases base definidas por el usuario, los métodos abstractos deben generar esta excepción cuando requieren que las clases derivadas anulen el método, o mientras se desarrolla la clase para indicar que aún se debe agregar la implementación real.

Tenga en cuenta que, aunque el principal caso de uso indicado es este error, es la indicación de métodos abstractos que deben implementarse en las clases heredadas, puede usarlo como quiera, como indicación de un marcador de TODO .


Considera si en cambio fue:

class RectangularRoom(object): def __init__(self, width, height): pass def cleanTileAtPosition(self, pos): pass def isTileCleaned(self, m, n): pass

y hace una subclase y se olvida de decirle cómo isTileCleaned() o, quizás lo más probable, lo isTileCLeaned() como isTileCLeaned() . Luego, en tu código, obtendrás un None cuando lo llames.

  • ¿Obtendrás la función anulada que querías? Definitivamente no.
  • ¿ None salida es válida? Quién sabe.
  • ¿Es ese comportamiento pretendido? Casi seguro que no.
  • ¿Recibirás un error? Depende.

raise NotImplmentedError te obliga a implementarlo, ya que lanzará una excepción cuando intentes ejecutarlo hasta que lo hagas. Esto elimina muchos errores silenciosos. Es similar a por qué una excepción desnuda casi nunca es una buena idea : porque las personas cometen errores y esto se asegura de que no sean barridos debajo de la alfombra.

Nota: el uso de una clase base abstracta, como han mencionado otras respuestas, es aún mejor, ya que los errores se cargan de antemano y el programa no se ejecutará hasta que los implemente (con NotImplementedError, solo lanzará una excepción si se llama).


Es posible que desee utilizar el decorador @property ,

>>> class Foo(): ... @property ... def todo(self): ... raise NotImplementedError("To be implemented") ... >>> f = Foo() >>> f.todo Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in todo NotImplementedError: To be implemented