В чем разница между операторами == и is в Python?

Ответ

Оператор == сравнивает значения объектов (равенство), в то время как is проверяет, ссылаются ли две переменные на один и тот же объект в памяти (идентичность).

  • a == b эквивалентно вызову a.__eq__(b). Проверяет, равны ли значения.
  • a is b эквивалентно id(a) == id(b). Проверяет, являются ли a и b одним и тем же объектом.

Пример

# Списки - изменяемые объекты
list_a = [1, 2, 3]
list_b = list_a      # b теперь ссылается на тот же объект, что и a
list_c = [1, 2, 3]   # c - это новый объект с таким же значением

print(f"list_a == list_b: {list_a == list_b}")  # True: значения равны
print(f"list_a is list_b: {list_a is list_b}")  # True: один и тот же объект

print(f"list_a == list_c: {list_a == list_c}")  # True: значения равны
print(f"list_a is list_c: {list_a is list_c}")  # False: разные объекты в памяти

Важный нюанс: Интернирование

Для оптимизации Python кэширует (интернирует) некоторые неизменяемые объекты, такие как малые целые числа (от -5 до 256) и короткие строки. В таких случаях is может вернуть True для разных переменных с одинаковым значением, хотя на это поведение не следует полагаться.

x = 256
y = 256
print(f"x is y: {x is y}")  # True: число интернировано

m = 257
n = 257
print(f"m is n: {m is n}")  # False: число не интернировано (в CPython)

Рекомендации

  1. Для сравнения значений (чисел, строк, списков) всегда используйте ==.
  2. Для проверки на None всегда используйте is, так как None является синглтоном. Это быстрее и является соглашением (PEP 8).
    if my_var is None:
        # ...
  3. Для проверки идентичности объектов используйте is, когда вам важно знать, что это один и тот же экземпляр в памяти.