1️⃣Класс 𝙸𝚝𝚎𝚖 определяет __𝚎𝚚__ для сравнения по значению 𝚡. Объекты 𝚊 и 𝚋 равны: 𝚊 == 𝚋 возвращает True.
2️⃣Но по умолчанию Python предполагает: если объекты могут быть равны по __𝚎𝚚__, то они должны иметь одинаковый хеш. Без явного __𝚑𝚊𝚜𝚑__ это нарушается.
3️⃣Поэтому Python автоматически устанавливает __𝚑𝚊𝚜𝚑__ = 𝙽𝚘𝚗𝚎, делая объекты нехешируемыми.
4️⃣При попытке создать {𝚊, 𝚋} выбрасывается TypeError: unhashable type: 'Item'.
Почему это важно Если нужны и сравнение, и хеширование (для 𝚜𝚎𝚝/𝚍𝚒𝚌𝚝), определите оба метода: __𝚎𝚚__ и __𝚑𝚊𝚜𝚑__, причём равные объекты должны иметь равные хеши.
1️⃣В словаре 𝚍 ключ "𝚊" существует и его значение — 𝙽𝚘𝚗𝚎.
2️⃣Вызов 𝚍.𝚐𝚎𝚝("𝚊", "𝚇"): ключ "𝚊" найден, возвращается его значение 𝙽𝚘𝚗𝚎, а не "𝚇".
3️⃣Вызов 𝚍.𝚐𝚎𝚝("𝚋", "𝚇"): ключа "𝚋" нет, возвращается значение по умолчанию "𝚇".
4️⃣Результат: 𝙽𝚘𝚗𝚎 𝚇.
Почему это важно Частая ошибка — использовать 𝚍.𝚐𝚎𝚝(𝚔𝚎𝚢) для проверки существования ключа: если значение 𝙽𝚘𝚗𝚎, результат неотличим от отсутствия ключа. Чтобы точно проверить наличие, используйте 𝚔𝚎𝚢 𝚒𝚗 𝚍 или обрабатывайте 𝙺𝚎𝚢𝙴𝚛𝚛𝚘𝚛.
Python сравнивает кортежи лексикографически: сначала первые элементы, потом вторые и так далее.
1️⃣Элемент 𝟶: 𝟷 == 𝟷 — равны, идём дальше.
2️⃣Элемент 𝟷: 𝟸 == 𝟸 — равны, идём дальше.
3️⃣У кортежа 𝚊 элементы закончились, а у 𝚋 ещё есть. По правилу: если один кортеж — префикс другого, то более короткий считается меньшим.
4️⃣Поэтому (𝟷, 𝟸) < (𝟷, 𝟸, 𝟶) возвращает True, даже несмотря на то что третий элемент 𝚋 — это 𝟶.
Почему это важно Это поведение совпадает с сортировкой слов в словаре: «кот» < «кота». Но при сортировке данных (например, версий (𝟷, 𝟸) vs (𝟷, 𝟸, 𝟶)) результат может быть неожиданным, если не учитывать правило «короче = меньше».
1️⃣Десятичная дробь 𝟶.𝟷 в двоичной системе — это бесконечная периодическая дробь, как 𝟷/𝟹 в десятичной. Компьютер хранит только приближение.
2️⃣То же самое с 𝟶.𝟸: сохраняется не точное значение, а ближайшее представимое в формате 𝚏𝚕𝚘𝚊𝚝.
3️⃣При сложении погрешности накапливаются, и результат 𝟶.𝟷 + 𝟶.𝟸 равен примерно 𝟶.𝟹𝟶𝟶𝟶𝟶𝟶𝟶𝟶𝟶𝟶𝟶𝟶𝟶𝟶𝟶𝟶𝟺.
4️⃣Сравнение с 𝟶.𝟹 (которое тоже хранится с погрешностью, но другой) даёт False. Почему это важно Сравнивать 𝚏𝚕𝚘𝚊𝚝 через == почти всегда неправильно. Для денег и точных вычислений используют модуль 𝚍𝚎𝚌𝚒𝚖𝚊𝚕, для приближённых сравнений — 𝚖𝚊𝚝𝚑.𝚒𝚜𝚌𝚕𝚘𝚜𝚎(𝚊, 𝚋) или проверку 𝚊𝚋𝚜(𝚊 - 𝚋) < 𝚎𝚙𝚜𝚒𝚕𝚘𝚗.
3️⃣В C, Java, JavaScript деление округляется к нулю, и там −𝟽 % 𝟹 = −𝟷.
Гвидо ван Россум намеренно выбрал округление вниз: при таком подходе остаток всегда попадает в диапазон [𝟶, 𝚗) при положительном делителе. Это удобно для вычисления номера клетки в сетке, индекса в кольцевом буфере, дня недели. Гвидо объяснял: если нужно округление к нулю, можно написать 𝚒𝚗𝚝(𝚊 / 𝚋), а вот получить «правильное» округление вниз из округления к нулю — сложнее, поэтому Python выбрал более полезный вариант по умолчанию. Почему это важно При портировании кода между языками или при работе с отрицательными координатами разница в поведении % может привести к трудноуловимым багам: один и тот же код даст разные результаты в Python и в C/Java.
1️⃣Список 𝚗𝚞𝚖𝚜 = [-𝟻, 𝟸, -𝟹, 𝟺]. Функция 𝚖𝚊𝚡 ищет элемент с максимальным значением.
2️⃣Параметр 𝚔𝚎𝚢=𝚊𝚋𝚜 означает: сравнивать элементы по их абсолютным значениям, то есть 𝟻, 𝟸, 𝟹, 𝟺.
3️⃣Максимум по модулю — это 𝟻 (от элемента −𝟻).
4️⃣Но 𝚖𝚊𝚡 возвращает сам элемент, а не результат 𝚔𝚎𝚢(𝚎𝚕𝚎𝚖𝚎𝚗𝚝), поэтому результат −𝟻, а не 𝟻.
Почему это важно Можно ожидать, что 𝚖𝚊𝚡(..., 𝚔𝚎𝚢=𝚏) вернёт 𝚏(𝚡), но это не так. Если нужен именно результат функции, придётся вызвать её отдельно: 𝚊𝚋𝚜(𝚖𝚊𝚡(𝚗𝚞𝚖𝚜, 𝚔𝚎𝚢=𝚊𝚋𝚜)) или 𝚖𝚊𝚡(𝚊𝚋𝚜(𝚡) 𝚏𝚘𝚛 𝚡 𝚒𝚗 𝚗𝚞𝚖𝚜).
1️⃣Создаётся объект 𝚋𝚊𝚐 с пустым списком 𝚒𝚝𝚎𝚖𝚜 = [].
2️⃣При проверке 𝚒𝚏 𝚋𝚊𝚐 Python сначала ищет __𝚋𝚘𝚘𝚕__ — его нет. Затем ищет __𝚕𝚎𝚗__ — тоже нет. 3️⃣Если ни один из методов не определён, объект считается truthy по умолчанию (он же существует!).
4️⃣Поэтому условие истинно и печатается full, хотя 𝚋𝚊𝚐.𝚒𝚝𝚎𝚖𝚜 пуст.
Почему это важно Многие ожидают, что 𝚒𝚏 𝚋𝚊𝚐 проверит содержимое, но Python не «заглядывает» внутрь объекта автоматически. Пустой список — falsy, но объект, содержащий пустой список — truthy. Чтобы получить ожидаемое поведение, нужно явно добавить __𝚕𝚎𝚗__ или __𝚋𝚘𝚘𝚕__, либо проверять 𝚒𝚏 𝚋𝚊𝚐.𝚒𝚝𝚎𝚖𝚜.