Como o Python 2 compara string e int? Por que as listas são comparadas como maiores que os números e as tuplas, maiores que as listas?


178

O seguinte snippet é anotado com a saída ( como visto em 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

Alguém pode explicar por que a saída é como tal?


Detalhes da implementação

  • Esse comportamento é determinado pelas especificações de idioma ou depende dos implementadores?
  • Existem diferenças entre as principais implementações do Python?
  • Existem diferenças entre as versões da linguagem Python?

23
Dos 3000 duplos desta pergunta, este tem uma resposta que explica por que o idioma foi projetado dessa maneira (e por que foi redesenhado no 3.x). Isso não faz parte desta pergunta, mas faz parte de muitas das perguntas vinculadas aqui.
abarnert

Respostas:


209

No manual python 2 :

Detalhe de implementação do CPython: Objetos de tipos diferentes, exceto números, são ordenados por seus nomes de tipo; objetos do mesmo tipo que não suportam comparação adequada são ordenados por seus endereços.

Quando você solicita duas sequências ou dois tipos numéricos, a ordenação é feita da maneira esperada (ordenação lexicográfica para sequência, ordenação numérica para números inteiros).

Quando você solicita um tipo numérico e um não numérico, o tipo numérico é o primeiro.

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

Quando você solicita dois tipos incompatíveis em que nenhum deles é numérico, eles são ordenados pela ordem alfabética de seus nomes de tipos:

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

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

Uma exceção são as classes de estilo antigo que sempre vêm antes das classes de novo estilo.

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

Esse comportamento é determinado pelas especificações de idioma ou depende dos implementadores?

Não há especificação de idioma . A referência de idioma diz:

Caso contrário, objetos de tipos diferentes sempre se comparam desiguais e são ordenados de maneira consistente, mas arbitrária.

Portanto, é um detalhe de implementação.

Existem diferenças entre as principais implementações do Python?

Não consigo responder a essa pergunta porque usei apenas a implementação oficial do CPython, mas existem outras implementações do Python, como o PyPy.

Existem diferenças entre as versões da linguagem Python?

No Python 3.x, o comportamento foi alterado para que a tentativa de solicitar um número inteiro e uma sequência de caracteres gere um erro:

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

55
Que bom que eles mudaram no Py3k. Quando vi essa pergunta pela primeira vez, meus pensamentos foram 'o que, isso não gera um erro?'.
JAL

9
NB Uma exceção à regra 2.x de que tipos diferentes são ordenados pelo nome do tipo é que o objeto None sempre se compara como menos que qualquer outro tipo. Na comparação 3.x, None com outro tipo ainda gerará um TypeError.
Dave Kirby

4
@KarelBilek: bool é um tipo numérico. E True == 1, então não é nem <nem>.
abarnert

3
Ordem Lexográfica de seus nomes de tipo? Quando você gostaria que isso fosse um recurso? Quem usaria isso?
21414 Jack

3
Curiosidade: complex(1,0) > 'abc'is Falsebut complex(1,0) > complex(0,0)raises aTypeError
Eric Duminil

24

As cadeias são comparadas lexicograficamente e tipos diferentes são comparados pelo nome do seu tipo ( "int"< "string"). 3.x corrige o segundo ponto, tornando-os não comparáveis.


3
Mas em python2, int é menor que dict, portanto não pode ser apenas lexicograficamente pelo nome do tipo?
Tony Suffolk 66

Acabei de encontrar esta resposta e concordo com Tony Suffolk. Os objetos NÃO são ordenados pelo nome do tipo quando diferentes.
Exelian

O tipo numérico do @ TonySuffolk66 é uma exceção a essa regra. NumericType é sempre menor que qualquer outro tipo (exceto NoneType) em 2.7.
LEF
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.