В чем разница между is и ==?

🔹 == vs is в Python: в чём разница?

В Python есть два оператора сравнения, которые могут показаться похожими, но на самом деле они сравнивают разные вещи:

Оператор Что сравнивает? Возвращает
\== Значения объектов (содержимое) True/False
--- --- ---
is Идентичность объектов (один ли объект в памяти) True/False
--- --- ---

🔸 ==: сравнение значений

Оператор == проверяет, одинаково ли содержимое двух объектов, даже если они находятся в разных местах памяти.

🔹 Пример:

a = \[1, 2, 3\]
b = \[1, 2, 3\]
print(a == b) # ✅ True — содержимое списков одинаковое

Списки a и b имеют одинаковое значение, но это разные объекты в памяти.

🔸 is: сравнение идентичности объектов

Оператор is проверяет, указывают ли обе переменные на один и тот же объект в памяти.

🔹 Пример:

a = \[1, 2, 3\]
b = \[1, 2, 3\]
print(a is b) # ❌ False — это два разных объекта

Несмотря на одинаковое содержимое, a и b — разные ссылки (адреса в памяти).

🔸 Подтверждение через id()

Функция id() возвращает уникальный идентификатор объекта (его адрес в памяти):

print(id(a)) # например, 139922224955264
print(id(b)) # другой адрес
print(a is b) # False

🔹 Когда is возвращает True?

Когда две переменные ссылаются на один и тот же объект:

a = \[1, 2, 3\]
b = a
print(a is b) # ✅ True — это один и тот же объект

🔸 Примеры с неизменяемыми типами

Python интернирует (кэширует) некоторые объекты: например, маленькие числа и строки.

Пример с числами:

a = 10
b = 10
print(a is b) # ✅ True (интернирование)
x = 5000
y = 5000
print(x is y) # ❌ Может быть False (вне интервала кэширования)

Пример со строками:

a = "hello"
b = "hello"
print(a is b) # ✅ Часто True — строки кэшируются
a = "hello world, this is long"
b = "hello world, this is long"
print(a is b) # ❌ Может быть False

🔸 Никогда не полагайся на is для строк или чисел, если тебе важно только сравнение значений — используй ==.

🔹 Когда использовать is правильно?

✅ Используй is в следующих случаях:

1. Сравнение с None

if value is None:
print("Нет значения")

Почему не ==?
Потому что None — это единственный объект типа NoneType, и лучше сравнивать его через is, чтобы избежать ошибок с перегруженным _eq_.

2. Проверка на идентичность объектов

if a is b:
print("Это один и тот же объект")

🔹 Когда нельзя использовать is?

  • Никогда не используй is для сравнения строк, чисел, списков, кортежей, если тебе важны значения.

  • Даже если a is b случайно вернёт True — это не гарантировано в будущем или на другой платформе.

🔸 Перегрузка ==

Оператор == использует метод _eq_(), который можно переопределить в своих классах:

class Person:
def \__init_\_(self, name):
self.name = name
def \__eq_\_(self, other):
return self.name == other.name
p1 = Person("Alice")
p2 = Person("Alice")
print(p1 == p2) # ✅ True (сравнивает имена)
print(p1 is p2) # ❌ False (разные объекты)

🔹 Таблица сравнения is vs ==

Особенность \== is
Сравнивает Значения Идентичность объектов
--- --- ---
Результат True, если содержимое совпадает True, если ссылки совпадают
--- --- ---
Переопределяемый Да (_eq_) Нет
--- --- ---
Используется с None Нет (нежелательно) ✅ Да
--- --- ---
Для объектов одного типа Да Только если это один объект
--- --- ---

🔹 Заключение

Вопрос Ответ
a == b Сравнивает значения
--- ---
a is b Проверяет — это один и тот же объект?
--- ---
Где is полезен? Сравнение с None, проверка на идентичность
--- ---
Где == предпочтительнее? Во всех остальных случаях
--- ---