1️⃣Переменная x объявляется в глобальной области видимости и получает значение 1.
2️⃣При вызове функции func интерпретатор встречает команду вывода переменной x.
3️⃣Поскольку внутри функции нет своей локальной переменной с таким именем, Python по правилу разрешения областей видимости (LEGB) поднимается на один уровень выше.
4️⃣В глобальной области находится нужная переменная, и на экран штатно выводится 1.
Почему это важно Это базовое правило работы с областями видимости. Важно твёрдо помнить, что чтение глобальных переменных работает прозрачно и «из коробки». Иногда новички ищут здесь подвох, ожидая ошибку, но проблемы начинаются только в момент попытки изменить такую переменную.
1️⃣Интерпретатор начинает чтение инструкции по созданию нового класса MyBool.
2️⃣В качестве родительского класса передаётся встроенный тип bool.
3️⃣В исходном коде CPython для структуры класса bool отсутствует специальный флаг Py_TPFLAGS_BASETYPE, который разрешает другим классам расширять его.
4️⃣Создание класса немедленно отклоняется с ошибкой TypeError: type 'bool' is not an acceptable base type.
5️⃣До функции print поток выполнения программы даже не добирается.
Почему это важно Это редкий пример жёсткого архитектурного ограничения в гибком Python. Понимание того, что базовые концепции истины и лжи аппаратно защищены от переопределения, уберегает от странных идей по созданию собственных логических типов, которые могли бы сломать стандартные проверки if в чужом коде.
1️⃣При создании словаря сначала добавляется пара True: "yes".
2️⃣Затем интерпретатор видит ключ 1. Так как тип bool наследуется от int, для питона True == 1. Их хэши тоже равны. Вместо создания нового ключа, обновляется значение старого: словарь становится {True: "no"}.
3️⃣Затем идёт ключ 1.0. Значение 1.0 == 1 == True. Снова происходит перезапись значения по существующему ключу.
4️⃣Итоговый словарь выглядит так: {True: "maybe"}. Его длина равна 1.
5️⃣При обращении d[True] мы получаем последнее сохранённое значение — "maybe".
Почему это важно Задачка наглядно демонстрирует устройство хэш-таблиц (словарей и множеств) под капотом. Ключи считаются одинаковыми не по совпадению типов, а если их хэши равны (hash(a) == hash(b)) и сами объекты равны (a == b). Это нужно помнить при смешивании разных числовых типов в ключах.
1️⃣Под капотом Python булевы значения являются обычными числами: True ведёт себя как 1, а False как 0.
2️⃣Первое действие в скобках: (x + y) превращается в (1 + 0), что даёт 1.
3️⃣Затем происходит умножение: 1 * 5 равно 5.
4️⃣Второе действие в скобках: (x == y) проверяет, равно ли True значению False. Это ложь, поэтому возвращается False, которое в математическом контексте равно 0.
5️⃣Итоговое сложение: 5 + 0 даёт результат 5.
Почему это важно С одной стороны, это позволяет писать изящные счётчики вроде sum(x > 0 for x in lst). С другой стороны, неочевидное смешивание булевых значений и арифметики может запутать читателя кода, поэтому злоупотреблять этим не стоит.
3️⃣Python запоминает, что нужно вернуть 1, но перед выходом из функции обязан выполнить блок finally
4️⃣Входим в finally → встречаем return 2
5️⃣Запомненное значение 1 безвозвратно отбрасывается
6️⃣Функция завершается с возвратом 2
7️⃣print(2) выводит 2
Почему это важно Никогда не используйте операторы управления потоком (return, break, continue) внутри finally. Это антипаттерн: он может скрывать исключения и ломать ожидаемую логику возврата значений из функции.
1️⃣Цикл for i in range(3) запускается: i принимает значения 0, 1, 2
2️⃣На каждой итерации создаётся лямбда lambda: i — но она не запоминает текущее значение i, а сохраняет лишь ссылку на имя i
3️⃣Список funcs теперь содержит три функции, каждая смотрит на одно и то же имя i
4️⃣Цикл завершился — переменная i в области видимости равна 2
5️⃣f() вызывается для первой лямбды → ищет i → находит 2 → возвращает 2
6️⃣То же самое для второй и третьей лямбды
7️⃣print([2, 2, 2]) выводит [2, 2, 2]
Почему это важно Классическая ловушка при создании коллбэков в цикле. Чтобы зафиксировать значение в момент создания, используйте аргумент по умолчанию: lambda i=i: i — он вычисляется сразу при создании функции.