¿Cómo compara Python 2 string e int? ¿Por qué las listas se comparan como mayores que los números y las tuplas como mayores que las listas?


178

El siguiente fragmento se anota con la salida ( como se ve en ideone.com ):

print "100" < "2"      # True
print "5" > "9"        # False

print "100" < 2        # False
print 100 < "2"        # True

print 5 > "9"          # False
print "5" > 9          # True

print [] > float('inf') # True
print () > []          # True

¿Alguien puede explicar por qué la salida es como tal?


Detalles de implementacion

  • ¿Es este comportamiento obligatorio por las especificaciones del lenguaje, o depende de los implementadores?
  • ¿Hay diferencias entre alguna de las principales implementaciones de Python?
  • ¿Hay diferencias entre las versiones del lenguaje Python?

23
De los 3000 duplicados de esta pregunta, esta tiene una respuesta que explica por qué el lenguaje fue diseñado de esta manera (y por qué fue rediseñado en 3.x). Eso no es parte de esta pregunta, pero es parte de muchas de las preguntas que se vinculan aquí.
abarnert

Respuestas:


209

Del manual de Python 2 :

Detalle de implementación de CPython: los objetos de diferentes tipos, excepto los números, están ordenados por sus nombres de tipo; Los objetos del mismo tipo que no admiten una comparación adecuada se ordenan por su dirección.

Cuando ordena dos cadenas o dos tipos numéricos, la ordenación se realiza de la manera esperada (ordenación lexicográfica para cadena, ordenación numérica para enteros).

Cuando solicita un tipo numérico y otro no numérico, el tipo numérico es lo primero.

>>> 5 < 'foo'
True
>>> 5 < (1, 2)
True
>>> 5 < {}
True
>>> 5 < [1, 2]
True

Cuando ordena dos tipos incompatibles donde ninguno es numérico, se ordenan por orden alfabético de sus nombres de tipo:

>>> [1, 2] > 'foo'   # 'list' < 'str' 
False
>>> (1, 2) > 'foo'   # 'tuple' > 'str'
True

>>> class Foo(object): pass
>>> class Bar(object): pass
>>> Bar() < Foo()
True

Una excepción son las clases de estilo antiguo que siempre vienen antes que las clases de estilo nuevo.

>>> class Foo: pass           # old-style
>>> class Bar(object): pass   # new-style
>>> Bar() < Foo()
False

¿Es este comportamiento obligatorio por las especificaciones del lenguaje, o depende de los implementadores?

No hay especificación de idioma . La referencia del lenguaje dice:

De lo contrario, los objetos de diferentes tipos siempre se comparan desiguales y se ordenan de manera consistente pero arbitraria.

Por lo tanto, es un detalle de implementación.

¿Hay diferencias entre alguna de las principales implementaciones de Python?

No puedo responder a esto porque solo he usado la implementación oficial de CPython, pero hay otras implementaciones de Python como PyPy.

¿Hay diferencias entre las versiones del lenguaje Python?

En Python 3.x, el comportamiento ha cambiado para que intentar ordenar un número entero y una cadena genere un error:

>>> '10' > 5
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    '10' > 5
TypeError: unorderable types: str() > int()

55
Es bueno que lo hayan cambiado en Py3k. Cuando vi por primera vez esta pregunta, mis pensamientos fueron "¿qué, esto no genera un error?".
JAL

9
NB Una excepción a la regla 2.x de que los diferentes tipos están ordenados por el nombre del tipo es que el objeto Ninguno siempre se compara como menor que cualquier otro tipo. En 3.x, comparar None con otro tipo aún generará un TypeError.
Dave Kirby

44
@KarelBilek: bool es un tipo numérico. Y True == 1, entonces no es ni <ni>.
abarnert

3
Orden Lexográfico de sus nombres de tipo? ¿Cuándo quieres que esto sea una característica? ¿Quién usaría eso alguna vez?
Jack

3
Dato curioso: complex(1,0) > 'abc'es Falsepero complex(1,0) > complex(0,0)plantea unTypeError
Eric Duminil

24

Las cadenas se comparan lexicográficamente, y los tipos diferentes se comparan por el nombre de su tipo ( "int"< "string"). 3.x corrige el segundo punto haciéndolos no comparables.


3
Pero en python2, los int son menos que dictos, por lo que no puede ser solo lexicográficamente por nombre de tipo.
Tony Suffolk 66

Acabo de encontrar esta respuesta y estoy de acuerdo con Tony Suffolk. Los objetos NO están ordenados por el nombre del tipo cuando son diferentes.
Exelian

El tipo numérico @ TonySuffolk66 es una excepción a esa regla. NumericType es siempre más bajo que cualquier otro tipo (excepto NoneType) en 2.7.
lef
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.