Как Python 2 сравнивает строку и int? Почему списки сравниваются как больше, чем числа, и кортежи больше, чем списки?


178

Следующий фрагмент аннотирован выводом ( как видно на 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

Может кто-нибудь объяснить, почему вывод таков?


Детали реализации

  • Это поведение предписано спецификацией языка или оно зависит от разработчиков?
  • Есть ли различия между основными реализациями Python?
  • Есть ли различия между версиями языка Python?

23
Из 3000 ответов на этот вопрос у этого есть ответ, объясняющий, почему язык был разработан таким образом (и почему он был перепроектирован в 3.x). Это не является частью этого вопроса, но является частью многих вопросов, которые здесь связаны.
abarnert

Ответы:


209

Из руководства по питону 2 :

Детали реализации CPython: объекты разных типов, кроме чисел, упорядочены по именам типов; объекты тех же типов, которые не поддерживают правильное сравнение, упорядочены по их адресу.

Когда вы заказываете две строки или два числовых типа, упорядочение выполняется ожидаемым образом (лексикографическое упорядочение для строки, числовое упорядочение для целых чисел).

Когда вы заказываете числовой и нечисловой тип, числовой тип стоит первым.

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

Когда вы заказываете два несовместимых типа, где ни один из них не является числовым, они упорядочиваются в алфавитном порядке их типов:

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

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

Единственным исключением являются классы старого стиля, которые всегда предшествуют классам нового стиля.

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

Это поведение предписано спецификацией языка или оно зависит от разработчиков?

Там нет спецификации языка . Справочник языка говорит:

В противном случае объекты разных типов всегда сравниваются неравно и упорядочены последовательно, но произвольно.

Так что это деталь реализации.

Есть ли различия между основными реализациями Python?

Я не могу ответить на этот вопрос, потому что я использовал только официальную реализацию CPython, но есть и другие реализации Python, такие как PyPy.

Есть ли различия между версиями языка Python?

В Python 3.x поведение было изменено, так что попытка упорядочить целое число и строку вызовет ошибку:

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

55
Это хорошо, что они изменили это в Py3k. Когда я впервые увидел этот вопрос, мои мысли были «что, это не вызывает ошибку?».
JAL

9
NB. Исключением из правила 2.x, согласно которому различные типы упорядочены по имени типа, является то, что объект None всегда сравнивается как меньший, чем любой другой тип. В 3.x сравнение None с другим типом все равно вызовет ошибку TypeError.
Дейв Кирби

4
@KarelBilek: bool - числовой тип. И True == 1, так что это ни <ни>.
abarnert

3
Лексографический порядок названий их типов? Когда бы вы хотели, чтобы это было функцией? Кто бы это использовал?
Джек,

3
Интересный факт: complex(1,0) > 'abc'это , Falseно complex(1,0) > complex(0,0)поднимаетTypeError
Эрик Duminil

24

Строки имеют по сравнению лексически, и разнородные типы сравниваются по имени их типа ( "int"< "string"). 3.x исправляет вторую точку, делая их несопоставимыми.


3
Но в python2 int меньше, чем dicts, поэтому он не может быть просто лексикографически по имени типа?
Тони Саффолк 66

Я только что наткнулся на этот ответ и согласен с Тони Саффолком. Объекты НЕ упорядочены по имени типа, когда они различаются.
Экзелиан,

@ TonySuffolk66 числовой тип является исключением из этого правила. NumericType всегда ниже, чем у любого другого типа (кроме NoneType) в 2.7.
ЛЕФ
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.