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

Ответ

Операторы == и is выполняют принципиально разные проверки:

  • == (оператор равенства): Сравнивает значения объектов. Вызывает метод __eq__() для определения, равны ли данные, которые хранят объекты.
  • is (оператор идентичности): Проверяет, ссылаются ли две переменные на один и тот же объект в памяти. Сравнивает идентификаторы объектов (id()).

Пример, демонстрирующий разницу:

list_a = [1, 2, 3]
list_b = list_a          # list_b — это ссылка на тот же объект
list_c = [1, 2, 3]       # list_c — новый объект с такими же значениями

print(list_a == list_b)  # True: значения одинаковы
print(list_a is list_b)  # True: это один объект (id(list_a) == id(list_b))

print(list_a == list_c)  # True: значения одинаковы
print(list_a is list_c)  # False: это разные объекты в памяти (id(list_a) != id(list_c))

Важные нюансы и best practice:

  • Кэширование мелких целых чисел и строк: Python интернирует небольшие целые числа (обычно от -5 до 256) и иногда строки для оптимизации. Поэтому a = 100; b = 100; a is b вернет True. Не полагайтесь на это поведение для сравнения значений.
  • Синглтоны None, True, False: Для сравнения с этими объектами всегда используйте is.
    if result is None:   # Правильно
    pass
    if result == None:   # Менее предпочтительно (хотя и работает)
    pass

    Главное правило: Для сравнения значений используйте ==. Для проверки, является ли переменная None, или для работы с синглтонами, используйте is.

Ответ 18+ 🔞

Слушай, а вот тут у людей реально мозг иногда сносит на раз-два, когда они пытаются понять разницу между == и is. Это ж, бля, как два разных инструмента в гараже: один — штангенциркуль, чтобы замерить размер, а второй — сварка, чтобы намертво соединить. И если ты будешь сваркой пытаться измерить деталь, будет тебе, ядрёна вошь, хиросима и нигасраки.

Вот смотри, простыми словами, чтобы волнение ебать не возникало.

  • == (оператор равенства): Этот чувак смотрит на содержимое. Ему похуй, где объект лежит в памяти. Его задача — понять, одинаковые ли данные внутри. Он такой: «Окей, у тебя список [1, 2, 3], и у тебя тоже список [1, 2, 3]. Значения совпадают? Ага. Значит, вы равны». Внутри он вызывает магический метод __eq__(), но это уже детали.
  • is (оператор идентичности): А этот — полный параноик. Ему доверия ебать ноль. Он проверяет, а не один ли это и тот же объект, одна и та же ячейка в оперативке. Он смотрит на внутренний паспорт объекта — его id(). «Вы оба ссылаетесь на одну и ту же хуйню? Нет? Тогда пошли нахуй, вы разные».

Вот тебе живой пример, чтобы сам от себя не охуеть:

list_a = [1, 2, 3]
list_b = list_a          # list_b — это просто ещё одна табличка на ту же квартиру. Один объект.
list_c = [1, 2, 3]       # list_c — это новая квартира, но с такой же мебелью. Другой объект.

print(list_a == list_b)  # True: мебель-то одинаковая!
print(list_a is list_b)  # True: это одна и та же квартира, Карл!

print(list_a == list_c)  # True: мебель опять одинаковая!
print(list_a is list_c)  # False: это РАЗНЫЕ квартиры! id(list_a) != id(list_c), ёпта!

А теперь ловушки, где все обламываются, как хитрая жопа на льду:

  1. Кэширование мелких целых чисел: Python, тот ещё пиздопроебибна, для оптимизации кэширует маленькие целые числа (обычно от -5 до 256). Поэтому a = 100; b = 100; a is b вернёт True. Но, чувак, ты веришь в эту магию? Нет. Никогда, блядь, не полагайся на это для сравнения значений. Это как надеяться, что в твоём пиве всегда будет бесплатный сухарик. Рано или поздно обосрёшься.

  2. Главное правило, которое надо впендюрить в башку: Для синглтонов None, True, FalseВСЕГДА используй is. Это железобетонно.

    if result is None:   # Правильно. Чётко, ясно, без вариантов.
        pass
    if result == None:   # Работать будет, но звучит как «залупа ты конская». Менее предпочтительно.
        pass

Итог, чтобы не было терпения ноль ебать: Хочешь сравнить, что внутри — жми ==. Хочешь проверить, не одна ли это и та же сущность в памяти (особенно с None) — твой выбор is. Всё просто, как три копейки.