Чем == отличается от is?
Рассмотрим на примере. Создадим словарь и скопируем ссылку на него:
Кстати, чтобы проверить, есть ли вообще у переменной значение, обычно пользуются оператором
выстрелить себе в ногу получить интересные результаты. Поэтому в PEP8 и рекомендуют проверять на значение
#основы #identity_vs_equality #перед_собесом #типы_данных
==
проверяет, одинаковые ли значения у переменных.is
проверяет, указывают ли переменные на один и тот же объект.Рассмотрим на примере. Создадим словарь и скопируем ссылку на него:
a = [1, 2, 3]Теперь создадим новый словарь с помощью копирования:
b = a
b is a # True
b == a # True
b = a[:]Но из-за того, что мы скопировали в новый объект все значения старого, то содержимое двух словарей все равно совпадает:
b is a # False
>>> b == a # TrueТо есть,
a is b
по сути то же, что id(a) == id(b)
. Поэтому если a is b
вернет True
, это будет значить, что и содержимое у них одинаковое. Просто потому что это один и тот же объект.Кстати, чтобы проверить, есть ли вообще у переменной значение, обычно пользуются оператором
is
, а не ==
:a = 42Дело в том, что класс
a is None # False
None
реализован как синглтон. Это значит, что экземпляр этого класса существует в интерпретаторе в единственном числе и все неопределенные значения указывают на него. a = NoneДля некоторых классов оператор
b = None
a is b # True
==
тоже сработает, но так лучше не делать, потому что в пользовательских классах этот оператор можно переопределить и None
именно с помощью is
. 🐍#основы #identity_vs_equality #перед_собесом #типы_данных
👍4🔥1
Кеширование небольших чисел в CPython
Поговорим о небольших числах в CPython. Возьмем, например, два числа, 10 и 300:
Все дело в том, что интерпретатор хранит числа в диапазоне от - 5 до 256 в специальном массиве. Поэтому когда мы пишем
И это снова не фича, а деталь реализации для экономии ресурсов. А пишу я об этом, потому что на задачу с кешем наткнулась на собеседовании, и собеседующий удивился, что я в курсе. Сказал, что узнал об этой особенности, когда начал сам проводить собеседования. Теперь это знаете и вы 🐍
#кеш #детали_реализации #low_level #identity_vs_equality
Поговорим о небольших числах в CPython. Возьмем, например, два числа, 10 и 300:
Что?! Почему
>>> a = 10
>>> b = 300
>>> a is 10
True
>>> b is 300
False
a
указыввет на свое значение, а b
y нет? Все дело в том, что интерпретатор хранит числа в диапазоне от - 5 до 256 в специальном массиве. Поэтому когда мы пишем
x = 10
, то вообще-то получаем ссылку на объект, который уже существует в памяти: Причем это касается любых значений, которые приводятся к целым числам этого диапазона. Можно завести число хоть в двоичном виде, хоть в hex, кеширование все равно будет работать:
>>> c = 1
>>> id(1)
94492411548416
>>> id(c)
94492411548416
Числа вне диапазона - 5, 256 интерпретатор тоже будет пытаться оптимизировать, но только если они находятся в одной строке (или одном файле). В командной строке интерпретатора так не работает:
>>> id(19)
94579033949504
>>> id(0b10011)
94579033949504
>>> id(0o23)
94579033949504
>>> id(0x13)
94579033949504
а так будет:
>>> d = 400
>>> d is 400
False
В общем и целом то, что нужно запомнить -- это что небольшие числа в интерпретаторе хранятся не так, как большие и что с ними следует пользоваться оператором
>>> e = 500; f = 500
>>> e is f
True
==
, а не is
. И это снова не фича, а деталь реализации для экономии ресурсов. А пишу я об этом, потому что на задачу с кешем наткнулась на собеседовании, и собеседующий удивился, что я в курсе. Сказал, что узнал об этой особенности, когда начал сам проводить собеседования. Теперь это знаете и вы 🐍
#кеш #детали_реализации #low_level #identity_vs_equality
🔥2👍1