Ответ
Операторы == и 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), ёпта!
А теперь ловушки, где все обламываются, как хитрая жопа на льду:
-
Кэширование мелких целых чисел: 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. Всё просто, как три копейки.
Видео-ответы
▶
▶
▶
▶
▶