Sin querer, time.clock<()
con la respuesta del intérprete de Python 2.7 siendo: True
. El siguiente código ejemplifica el comportamiento:
>>> repr(time.clock) '' >>> time.clock<() True
Además:
>>> import sys >>> sys.maxint >> map(lambda _:0<_,((),[],{})) [True, True, True]
A diferencia de:
>>> 1<set(()) TypeError: can only compare to a set
Pregunta: Además de por qué, ¿hay un significado o propósito práctico de una list
vacía, tuple
o dict
evalúa como si fuera mayor que cualquier número?
Actualización :
Viktor señaló que las direcciones de memoria se comparan por defecto:
>>> map(lambda _:(id(0),'<',id(_)),((),[],{}, set([])))
[(31185488L, '<', 30769224L), (31185488L, '<', 277144584L), (31185488L, '<', 279477880L), (31185488L, '<', 278789256L)]
A pesar del orden aparente, esto es incorrecto .
Sin un operador de comparación explícito definido, Python 2 se compara por Números y Nombres de tipo, con los números con la prioridad más baja.
Esto no sugiere qué métodos internos exactos se están invocando. Vea también este útil pero no concluyente hilo de SO :
En un IPython 2.7.5 REPL
>>> type(type(()).__name__) Out[15]: str >>> type(()) >> 10 >> type(()) >> type(()) == type(()) Out[10]: True However: >>> 'somestr' .__le__(10) Out[20]: NotImplemented >>> 'somestr' .__lt__(10) Out[21]: NotImplemented >>> int.__gt__ Out[25]: >>> int.__lt__ Out[26]: >>> int.__lt__(None) Out[27]: NotImplemented #.....type(...), dir(...), type, dir...... #An 'int' instance does not have an >> 0 .__lt__ Out[28]: AttributeError: 'int' object has no attribute '__lt__' #int is actually a subclass of bool >>>int.__subclasses__() Out: [bool] #str as the fallback type for default comparisons >>> type(''.__subclasshook__) Out[72]: builtin_function_or_method >>> dir(''.__subclasshook__) Out[73]: ['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__'] #IPython is subclassing 'str' >>> str.__subclasses__() Out[84]: [IPython.utils.text.LSString]
En Python 2, cuando se comparan diferentes tipos, python ordena los tipos numéricos antes que todo lo demás, y entre el rest clasifica los tipos por tipo de nombre .
Por lo tanto, los enteros se ordenan antes de las tuplas, pero las instancias de la clase Foo
se ordenarán después de las instancias de la clase Bar
.
Python 3 elimina esta locura; comparando diferentes tipos de resultados en un TypeError en su lugar:
>>> 10 < () Traceback (most recent call last): File "", line 1, in TypeError: unorderable types: int() < tuple()
El tipo set()
Python ha sobrecargado el operador >
al implementar el método mágico __gt__
o 'mayor que'; se llama para la expresión 1 < set()
porque el tipo int
no tiene __lt__
, lower-then y Python prueba el inverso en ese caso; después de todo, x < y
es verdadero si y > x
es verdadero.
El gancho del set.__gt__()
genera un TypeError
cuando el otro operando no es un set
:
>>> 1 .__lt__(set()) Traceback (most recent call last): File "", line 1, in AttributeError: 'int' object has no attribute '__lt__' >>> set().__gt__(1) Traceback (most recent call last): File "", line 1, in TypeError: can only compare to a set
El operador sobrecargado >
(mayor que) para los conjuntos se usa para probar si el operando de la izquierda es un superconjunto apropiado del operando de la derecha . (Técnicamente, los objetos set
implementan la función PyTypeObject.tp_richcompare
C-API, no el __gt__
directamente, pero el __gt__
traduce en una llamada tp_richcompare
en ese caso automáticamente).
Cuando un método de comparación sobrecargado (uno de .__lt__()
, .__le__()
, .__eq__()
. __ne__()
. __gt__()
. __ge__()
, o . __cmp__()
) devuelve el objeto singleton No NotImplemented
este indica que la comparación no es compatible y Python vuelve al comportamiento predeterminado. Este comportamiento predeterminado, como ya se indicó en ¿Cómo funcionan los operadores de comparación de Python
Para Python 3, un NotImplemented
comparación que devuelve NotImplemented
hace que Python NotImplemented
TypeError
:
>>> class Foo(): ... def __lt__(self, other): return NotImplemented ... >>> Foo() < Foo() Traceback (most recent call last): File "", line 1, in TypeError: unorderable types: Foo() < Foo()
Python 2 es más terco y cuando se devuelve NotImplemented
o no se han implementado enganches, el código C termina en la función default_3way_compare()
C , que:
None
antes de nada (línea 780-783) PyNumber_Check
prueba que el nombre del tipo esté vacío, líneas 786-793) v->ob_type->tp_name
y w->ob_type->tp_name
en las líneas 786-793)