Почему 4 <'3' возвращает True в Python 2? - PullRequest
23 голосов
/ 01 ноября 2011

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

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

Ответы [ 3 ]

31 голосов
/ 01 ноября 2011

Да, любое число будет меньше, чем любая строка (включая пустую строку) в 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 имена типов сравниваются с пустой строкой, используемой вместо имени типа для любого числового типа.

7 голосов
/ 01 ноября 2011

Из документации 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()
0 голосов
/ 01 ноября 2011

Операция сравнения по умолчанию в 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 для повышения производительности.

...