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

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

Условие задачи Какой результат будет выведен на экран при выполнении данного кода?

class FooCollection:
    foo_1 = int("2" + "2") == int("22")
    foo_2 = int("22" + "22") == int("2222")
    foo_3 = int("2" + "2") is int("22")
    foo_0 = int("22" + "22") is int("2222")

print(all([getattr(FooCollection(), f"foo_{x}") for x in range(4)])) >>
Спойлеры к решению
Подсказки
  • Оператор == сравнивает значения.
  • Оператор is сравнивает идентичность объектов в памяти.
  • foo_1 и foo_2 будут True, потому что значения чисел одинаковые.
  • foo_3 в CPython обычно будет True, потому что маленькие целые числа кэшируются.
  • foo_0 обычно будет False, потому что 2222 не входит в стандартный диапазон кэшируемых маленьких чисел.
  • all() вернёт True только если все элементы списка истинные.
Решение
class FooCollection:
    foo_1 = int("2" + "2") == int("22")
    foo_2 = int("22" + "22") == int("2222")
    foo_3 = int("2" + "2") is int("22")
    foo_0 = int("22" + "22") is int("2222")


print(all([getattr(FooCollection(), f"foo_{x}") for x in range(4)]))

Результат:

False

Разбор:

foo_1 = int("2" + "2") == int("22")

"2" + "2" даёт строку "22", поэтому сравнение превращается в:

22 == 22

Результат:

True

Дальше:

foo_2 = int("22" + "22") == int("2222")

"22" + "22" даёт строку "2222", поэтому:

2222 == 2222

Результат:

True

Дальше:

foo_3 = int("2" + "2") is int("22")

В CPython маленькие целые числа обычно кэшируются. Число 22 относится к таким числам, поэтому оба выражения могут ссылаться на один и тот же объект.

Результат в CPython:

True

Дальше:

foo_0 = int("22" + "22") is int("2222")

Значение 2222 одинаковое, но это уже не маленькое кэшируемое число. Поэтому два вызова int() обычно создают разные объекты.

Результат в CPython:

False

Затем выполняется:

[getattr(FooCollection(), f"foo_{x}") for x in range(4)]

Это даёт список:

[foo_0, foo_1, foo_2, foo_3]

То есть:

[False, True, True, True]

Поэтому:

all([False, True, True, True])

вернёт:

False

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