Подтвердить что ты не робот

Почему 4 <'3' возвращает True в Python 2?

Почему 4 < '3' возвращает True в Python 2?

Это потому, что когда я помещаю одиночные кавычки вокруг числа, Python видит это как строку, а строки больше, чем числа?

4b9b3361

Ответ 1

Да, любое число будет меньше любой строки (включая пустую строку) в Python 2.

В Python 3 вы не можете производить произвольные сравнения. Вы получите TypeError.


От ссылка в комментарии eryksun:

if (PyNumber_Check(v))
    vname = "";
else
    vname = v->ob_type->tp_name;
if (PyNumber_Check(w))
    wname = "";
else
    wname = w->ob_type->tp_name;
c = strcmp(vname, wname);

Итак, по крайней мере, в последних версиях CPython 2.x имена типов сравниваются с пустой строкой, используемой вместо имени типа для любого числового типа.

Ответ 2

Из документации Python v2.7.2

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

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

Когда вы заказываете строку и целое число, имена типов упорядочиваются. "str" лексикографически после "int", "float", "long", "list", "bool" и т.д. Однако кортеж будет заказывать выше строки, потому что "tuple" > "str":

0 > 'hi'
False
[1, 2] > 'hi'
False
(1, 2) > 'hi'
True

также см. сравнение использует лексикографическое упорядочение от docs.python.org

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

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

Ответ 3

Операция сравнения по умолчанию в cpython 2 основана на адресе памяти рассматриваемого объекта. От type_richcompare() в python 2.7:

/* Compare addresses */
vv = (Py_uintptr_t)v;
ww = (Py_uintptr_t)w;
switch (op) {
case Py_LT: c = vv <  ww; break;
case Py_LE: c = vv <= ww; break;
case Py_EQ: c = vv == ww; break;
case Py_NE: c = vv != ww; break;
case Py_GT: c = vv >  ww; break;
case Py_GE: c = vv >= ww; break;
default:
    result = Py_NotImplemented;
    goto out;
}
result = c ? Py_True : Py_False;

Это действительно хорошо работает для равенства и неравенства, но может быть контринтуитивным для операций упорядочения, поэтому оно было изменено для Python 3. В самом деле, 2.7 выдаст предупреждение для таких случаев использования, если задан флаг -3.

Чтобы увидеть адрес памяти для данного объекта, вы можете использовать встроенную функцию id(). Он определен только для того, чтобы возвращать что-то уникальное для каждого отдельного объекта, но cpython использует адрес памяти объекта как удобный ярлык.

Маленькие целые числа имеют меньшие адреса памяти, чем короткие строки, по крайней мере в некоторых версиях python, вероятно, из-за кэширования, используемого cpython для повышения производительности.