Porque tienen diferentes casos de uso.
Citando los documentos (Python 3.6):
No se ha implementado
debe ser devuelto por los métodos especiales binarios (por ejemplo __eq__()
,
__lt__()
, __add__()
, __rsub__()
, etc.) para indicar que la operación no se lleva a cabo con respecto al otro tipo
excepción NotImplementedError
[...] En las clases base definidas por el usuario, los métodos abstractos deberían generar esta excepción cuando requieren clases derivadas para anular el método, o mientras se desarrolla la clase para indicar que la implementación real aún necesita ser agregada.
Vea los enlaces para más detalles.