¿Por qué es int (50) <str (5) en python 2.x?

En Python 3, int(50)<'2' causa un TypeError , y bueno debería. Sin embargo, en python 2.x, int(50)<'2' devuelve True (este también es el caso para otros formatos de números, pero int existe tanto en py2 como en py3). Mi pregunta, entonces, tiene varias partes:

  1. ¿Por qué Python 2.x (<3?) Permite este comportamiento?
    • (¿Y quién pensó que era una buena idea permitir que esto comience con ???)
  2. ¿Qué significa que un int es menos que un str ?
    • ¿Se refiere a ord / chr ?
    • ¿Hay algún formato binario que sea menos obvio?
  3. ¿Hay una diferencia entre '5' y u'5' en este aspecto?

Funciona así 1 .

 >>> float() == long() == int() < dict() < list() < str() < tuple() True 

Los números se comparan como menos que los contenedores. Los tipos numéricos se convierten en un tipo común y se comparan según su valor numérico. Los contenedores se comparan por el valor alfabético de sus nombres. 2

De los documentos :

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 están ordenados por su dirección.

Los objetos de diferentes tipos incorporados se comparan alfabéticamente por el nombre de su tipo int comienza con una 'i' y str comienza con una s por lo que cualquier int es menor que cualquier str . .

  1. No tengo idea.
    • Un maestro borracho.
  2. Significa que se ha introducido una orden formal en los tipos incorporados.
    • Se trata de una orden arbitraria.
    • No.
  3. No. Las cadenas y los objetos Unicode se consideran iguales para este propósito. Pruébalo.

En respuesta al comentario sobre long < int

 >>> int < long True 

Sin embargo, probablemente quiso decir valores de esos tipos, en cuyo caso se aplica la comparación numérica.

1 Esto es todo en Python 2.6.5

2 Gracias a kRON por aclararme esto. Nunca había pensado comparar un número con un dict anterior y la comparación de números es una de esas cosas que es tan obvia que es fácil pasar por alto.

La razón por la que se permiten estas comparaciones, es la clasificación. Python 2.x puede ordenar listas que contienen tipos mixtos, incluidas cadenas y enteros; los enteros siempre aparecen primero. Python 3.x no lo permite, por las razones exactas que señalaste.

Python 2.x:

 >>> sorted([1, '1']) [1, '1'] >>> sorted([1, '1', 2, '2']) [1, 2, '1', '2'] 

Python 3.x:

 >>> sorted([1, '1']) Traceback (most recent call last): File "", line 1, in  TypeError: unorderable types: str() < int() 

(¿Y quién pensó que era una buena idea permitir que esto comience con ???)

Puedo imaginar que la razón podría ser permitir que los objetos de diferentes tipos se almacenen en estructuras tipo árbol, que utilizan comparaciones internas.

Como dijo Aaron. Rompiéndolo en tus puntos:

  1. Debido a que hace que la ordenación haga algo que se puede usar hasta la mitad donde no tendría ningún sentido (listas mixtas). No es una buena idea en general, pero mucho en Python está diseñado para ser más práctico que estricto.
  2. Ordenado por nombre de tipo. Esto significa cosas del mismo tipo de grupo, donde se pueden clasificar. Probablemente deberían agruparse por clase de tipo, como números, pero no existe un marco de clase de tipo adecuado. Puede haber algunas reglas más específicas allí (probablemente es una para los tipos numéricos), tendría que verificar la fuente.
  3. Una es cadena y la otra es unicode. Sin embargo, pueden tener una operación de comparación directa, pero es concebible que un tipo no comparable se agrupara entre ellos, causando un desorden. No sé si hay código para evitar esto.

Por lo tanto, no tiene sentido en el caso general, pero en ocasiones es útil.

 from random import shuffle letters=list('abcdefgh') ints=range(8) both=ints+letters shuffle(ints) shuffle(letters) shuffle(both) print sorted(ints+letters) print sorted(both) 

Ambas imprimen las letras primero, luego las letras.

Como regla general, no desea mezclar tipos al azar dentro de un progtwig, y ​​al parecer Python 3 evita que Python 2 intente tener un sentido vago donde no existe ninguno. Aún puede ordenar por lambda a,b: cmp(repr(a),repr(b)) (o algo mejor) si realmente lo desea, pero parece que los desarrolladores del lenguaje acordaron que es un comportamiento predeterminado poco práctico. Espero que varíe lo que da la menor sorpresa, pero es mucho más difícil detectar un problema en el sentido de Python 2.