2009-06-30 12 views
24

Mirando a través de decimal.py, usa NotImplemented en muchos métodos especiales. p.ej.Constante Python NotImplemented

class A(object): 
    def __lt__(self, a): 
     return NotImplemented 

    def __add__(self, a): 
     return NotImplemented 

El Python docs say:

NotImplemented

valor especial que puede ser devuelto por los “ricos comparación” métodos especiales (__eq__(), __lt__(), y amigos), para indicar que la comparación no está implementada con respecto del otro tipo.

No habla de otros métodos especiales y tampoco describe el comportamiento.

Parece ser un objeto mágico que si se devuelve desde otros métodos especiales aumenta TypeError, y en "comparación rica" ​​los métodos especiales no hacen nada.

p. Ej.

print A() < A() 

impresiones True, pero

print A() + 1 

plantea TypeError, así que estoy curioso en cuanto a lo que está pasando y lo que es el uso/comportamiento de NotImplemented.

+2

Todo correcto. Usted ha descrito completamente NotImplemented. ¿Cuál es la pregunta? –

+0

mi pregunta era que si en el documento, menciona especialmente métodos especiales de "comparación enriquecida", otros métodos deberían ignorarlo, después de todo, es solo otro objeto, no pude encontrar el documento explicando el comportamiento general o cómo manejar NotImplemented –

Respuesta

26

NotImplemented le permite indicar que no se ha implementado una comparación entre los dos operandos dados (en lugar de indicar que la comparación es válida, pero produce False, para los dos operandos).

Desde el Python Language Reference:

para los objetos X e Y, en primer lugar x.__op__(y) es juzgado. Si esto no se implementa o devuelve NotImplemented, se intenta y.__rop__(x). Si esto también es no implementado o devuelve NotImplemented, se genera una excepción TypeError . Pero ver la siguiente excepción:

Excepción al elemento anterior : si el operando de la izquierda es una instancia de un tipo incorporado o una clase de nuevo estilo, y el operando derecho es una instancia de una adecuada subclase de ese tipo o clase y anula el método de base de __rop__(), el método de la derecha de operando __rop__() se trató antes método del operando de la izquierda __op__() . Esto se hace para que una subclase pueda anular completamente los operadores binarios .De lo contrario, el método de la izquierda de operando __op__() sería siempre aceptar el operando de la derecha: cuando se espera un instancia de una clase dada, una instancia de una subclase de esta clase es siempre aceptable.

+3

ok, entonces en general, el comportamiento es si el valor de retorno es NotImplemented intente algo más, si eso no es posible raise TypeError –

+0

¿Es una mala idea usarlo en otros contextos, como, por ejemplo, un mapeo de diccionario entre diferentes tipos? – endolith

4

En realidad, tiene el mismo significado cuando regresó de __add__ a partir __lt__, la diferencia es Python 2.x está tratando de otras formas de comparar los objetos antes de abandonar. Python 3.x genera un TypeError. De hecho, Python puede probar otras cosas para __add__ también, mira __radd__ y (aunque estoy confusa) __coerce__.

# 2.6 
>>> class A(object): 
... def __lt__(self, other): 
...  return NotImplemented 
>>> A() < A() 
True 

# 3.1 
>>> class A(object): 
... def __lt__(self, other): 
...  return NotImplemented 
>>> A() < A() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unorderable types: A() < A() 

Ver Ordering Comparisions (3.0 docs) para obtener más información.

0

Si lo devuelve desde __add__ se comportará como si el objeto no tiene el método __add__, y levanta un TypeError.

Si devuelve NotImplemented desde una función de comparación enriquecida, Python se comportará como si el método no se hubiera implementado, es decir, diferirá al uso de __cmp__.