В чем разница между операторами == и 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, когда вам важно знать, что это один и тот же экземпляр в памяти.

Ответ 18+ 🔞

А, слушай, смотри, тут у людей в голове пиздец какой-то творится с этими операторами == и is. Думают, одно и то же, блядь. А это, сука, как небо и земля, в рот меня чих-пых!

Вот смотри, пальцами объясню, чтобы даже мартышлюшка поняла.

  • a == b — это как спросить: «Эй, чувак, у вас в карманах одинаковая хуйня лежит?». Значения сравнивает. Вызвается магический метод .__eq__(), если ты в курсе.
  • a is b — это уже вопрос посерьёзнее: «Эй, мудила, а вы вообще один и тот же человек?». Проверяет, не одна ли это и та же сущность в памяти компа. По сути, это id(a) == id(b).

Вот тебе живой пример, смотри не обосрись:

# Списки — они как бабы, изменчивые, блядь.
list_a = [1, 2, 3]
list_b = list_a      # Б — это просто погоняло для того же самого объекта А. Одна жопа на двоих.
list_c = [1, 2, 3]   # С — это уже новая, отдельная жопа. Хоть и набита тем же самым.

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 — внутри всё то же самое, 1,2,3.
print(f"list_a is list_c: {list_a is list_c}")  # False — а вот это уже РАЗНЫЕ ЖОПЫ! Разные объекты в памяти, хоть и близнецы-братья.

А теперь, внимание, ебушки-воробушки, подвох!

Пайтон, он хитрая жопа, иногда оптимизирует. Маленькие циферки (типа от -5 до 256) и короткие строки он кэширует, называется «интернирование». Так вот, для них is может сработать, как ==, но НА ЭТО НЕЛЬЗЯ РАССЧИТЫВАТЬ, ёпта! Это как надеяться, что тебе повезёт в лотерее — доверия ебать ноль.

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 — а вот тут уже похуй, две отдельные 257 в памяти. В CPython так точно.

Так как же жить-то, блядь? Краткий гид по выживанию:

  1. Хочешь сравнить, что внутри? Числа, строки, списки — всегда юзай ==. «Значения равны?»
  2. Проверяешь на None? Только is, и точка! None — он один такой на весь мир, синглтон. И так быстрее, и все умные дяди в PEP 8 так велят.
    if my_var is None:  # Да, вот так, идеально.
        # ...
  3. Тебе реально важно, что это один и тот же экземпляр, а не клон? Ну, типа, не просто две одинаковые бутылки водки, а именно ЭТА самая бутылка, из которой мы вчера пили? Вот тогда is. Во всех остальных случаях — ==.

Вот и вся магия, хуй с горы. Не путай, а то код потом ведёт себя как пизда с ушами, и ты сидишь и думаешь: «Я от себя охуел, что происходит?».