В Python есть восемь операций сравнения. Все они имеют одинаковый приоритет, который выше, чем у логических операций.
Разрешенные операции сравнения:
x < y
- строго x
меньше y
,x <= y
- x
меньше или равно y
,x > y
- строго x
больше y
,x >= y
- x
больше или равно y
,x == y
- x
равно y
,x != y
- x
не равно y
.Внимание!. Комплексным числам (тип complex
) недоступны операции: x < y
, x <= y
, x > y
и x >= y
.
Сравнения могут быть связаны произвольно и записаны в цепочки сравнений, в которых для соединения сравнений используются неявные логические операторы and
.
x < y <= z
# эквивалентно
x < y and y <= z
В примере выше y
вычисляется только один раз. Если x < y
оказывается ложным, то в обоих случаях, приведенных выше z
не оценивается вообще.
Еще пример:
a < b <= c < d
# эквивалентно
a < b and b <= c and c < d
В такой форме сравнения легче читаются, и каждое подвыражение вычисляется по крайней мере один раз. Так же читайте о результатах смешивание операторов is
и in
в цепочках сравнений"
Объекты разных типов, за исключением различных числовых типов, никогда не будут равными.
Оператор ==
всегда определен, но для некоторых типов объектов, например объектов класса, эквивалентен оператору идентичности is
.
Операторы <
, <=
, >
и >=
применяются только там, где они имеют смысл, например они вызывают исключение TypeError
, когда один из аргументов является комплексным числом.
Неидентичные экземпляры класса обычно при сравнении будут неравны, если только класс не определяет метод __eq__()
.
Экземпляры класса не могут быть упорядочены относительно других экземпляров того же класса или других типов объектов, если класс не определяет достаточное количество методов __lt__()
, __le__()
, __gt__()
и __ge__()
. В общем случае определение методов __lt__()
и __eq__()
для этих целей бывает достаточно.
Следующий список описывает поведение сравнения наиболее важных встроенных типов:
Числа встроенных числовых типов int
, float
, complex
и стандартных библиотечных типов fractions.Fraction
и decimal.Decimal
можно сравнивать внутри и между их типами, с ограничением, что комплексные числа не поддерживают сравнение порядка. В пределах задействованных типов они сравнивают математически (алгоритмически) правильно без потери точности.
Нечисловые значения float('NaN')
и decimal.Decimal('NaN')
являются особыми. Любое упорядоченное сравнение числа с нечисловым значением неверно. Нечисловые значения не равны самим себе. Например, если x = float('NaN')
, 3 < x
, x < 3
и x == x
все ложны, а x! = X
истинно. Это поведение соответствует стандарту IEEE 754.
None и NotImplemented являются одиночными. PEP 8 советует, что сравнения для одиночных экземпляров всегда должны выполняться с использованием или нет, а не с операторами равенства.
Двоичные последовательности (экземпляры bytes
или bytearray
) можно сравнивать внутри и между их типами. Они сравнивают лексикографически, используя числовые значения своих элементов.
Строки (экземпляры str
) лексикографически сравниваются с использованием числовых кодовых точек Unicode (результат встроенной функции ord()
) их символов.
Строки и двоичные последовательности нельзя сравнивать напрямую.
Последовательности (экземпляры tuple
, list
или range
) можно сравнивать только в пределах каждого из их типов с ограничением, что диапазоны range
не поддерживают сравнение порядка (сортировку). Операция равенства между этими типами приводит к неравенству, а сравнение порядка между этими типами вызывает исключение TypeError
.
Последовательности сравнивают лексикографически с помощью сравнения соответствующих элементов. Встроенные контейнеры обычно предполагают, что идентичные объекты равны самим себе. Это позволяет им обходить тесты на равенство для идентичных объектов, чтобы повысить производительность и сохранить свои внутренние инварианты.
Лексикографическое сравнение встроенных коллекций работает следующим образом:
Чтобы две коллекции были равными, они должны быть одного типа, иметь одинаковую длину и каждая пара соответствующих элементов должна быть равной. Например [1,2] == (1,2)
ложно, потому что типы последовательностей разные.
Коллекции, поддерживающие сравнение порядка (сортировку), упорядочиваются так же, как их первые неравные элементы, например [1,2, x] <= [1,2, y]
имеет то же значение, что и x <= y
. Если соответствующий элемент не существует, то более короткая коллекция при сортировке встанет первой, например [1,2] < [1,2,3]
истинно).
Множества (экземпляры set
или frozenset
) можно сравнивать внутри и между их типами.
Они определяют операторы сравнения порядка для обозначения тестов подмножества и надмножества. Эти отношения не определяют общий порядок. Например два множества {1,2}
и {2,3}
не равны, ни подмножества друг друга, ни надмножества друг друга. Соответственно, наборы не являются подходящими аргументами для функций, которые зависят от общего упорядочения. Например min()
, max()
и sorted()
дают неопределенные результаты при наличии списка множеств в качестве входных данных.
Большинство других встроенных типов не имеют реализованных методов сравнения, поэтому они наследуют поведение сравнения по умолчанию.
>>> a = 8
>>> b = 3
>>> a == b
# False
>>> a < b
# False
>>> a != b
# True
>>> a = 2
>>> b = 6
>>> c = 10
>>> a < b < c
# True
>>> a != b != c
# True
>>> a == b == c
# False
>>> 0 < b < 5
# False
Важно:
Числа типа float
не являются десятичными дробями и используют двоичную арифметику, поэтому иногда выражения могут вычисляться с ничтожно малыми погрешностями. Из-за этих погрешностей операции сравнения работают не так как ожидается.
>>> 0.8 - 0.5 - 0.3 == 0
# False
>>> 0.8 - 0.5 - 0.3
# 5.551115123125783e-17
>>> 10.5 + 4.1 + 6.4 == 21
True
>>> 10.5 + 4.1 + 6.4
# 21.0