is сравнивает идентичность объектов (то есть, указывают ли переменные на одну и ту же область памяти).== (operator eq) сравнивает значения, то есть равны ли объекты с точки зрения их содержимого.is следует использовать для сравнения именно идентичности (например, с None или для singleton-объектов), а не для проверки равенства значений.
Пример:
a = [1, 2, 3] b = [1, 2, 3] print(a == b) # True print(a is b) # False c = None d = None print(c is d) # True
При работе с небольшими целыми числами или строками интерпретатор может использовать "интернирование" (cached objects), что иногда делает is истинным для равных значений, но это не должно использоваться в логике программы.
Вопрос: Что выведет следующий код?
a = 256 b = 256 print(a is b) c = 257 d = 257 print(c is d)Почему?
Ответ:
Для значений от -5 до 256 Python использует пул целых чисел. Значения в этом диапазоне всегда указывают на одни и те же объекты, поэтому a is b даст True. 257 — уже вне пула, поэтому c is d будет False (объекты независимы).
История
В одном микросервисе проверку равенства строк провели с помощью is вместо ==. Из-за оптимизаций интерпретатора программа работала "стабильно" в тестах, но начала сбоить после перекомпиляции или других изменений среды.
Один разработчик для сравнения чисел использовал оператор is вместо ==. Это сработало для маленьких чисел (благодаря пулу), но для больших — дало сбои и непредсказуемые результаты, что вызвало некорректную работу расчётов.
В проектирование системы авторизации проверяли пришедший JSON с помощью is None (корректно), а затем по аналогии сделали так же для строк: if status is "ok". Это оказалось ошибкой — иногда условие не выполнялось, приводя к неверной логике обработки данных.