Python: задачки и вопросы
Відкрити в Telegram
Вопросы и задачки для подготовки к собеседованиям и прокачки навыков Разместить рекламу: @tproger_sales_bot Правила общения: https://tprg.ru/rules Другие каналы: @tproger_channels Другие наши проекты: https://tprg.ru/media
Показати більше6 963
Підписники
+124 години
-67 днів
-6130 день
Архів дописів
Развёрнутое пояснение
1️⃣Переменной 𝚊 присваивается целое число 𝟷.
2️⃣В выражении 𝚋 = (𝚊) скобки играют только роль группировки — результатом остаётся то же значение 𝟷, и 𝚋 ссылается на обычное целое; поэтому 𝚝𝚢𝚙𝚎(𝚋) 𝚒𝚜 𝚝𝚞𝚙𝚕𝚎 возвращает False.
3️⃣В выражении 𝚌 = (𝚊,) уже есть запятая, которая и создаёт одноэлементный кортеж; поэтому 𝚝𝚢𝚙𝚎(𝚌) 𝚒𝚜 𝚝𝚞𝚙𝚕𝚎 даёт True.
4️⃣Функция 𝚙𝚛𝚒𝚗𝚝(𝚝𝚢𝚙𝚎(𝚋) 𝚒𝚜 𝚝𝚞𝚙𝚕𝚎, 𝚝𝚢𝚙𝚎(𝚌) 𝚒𝚜 𝚝𝚞𝚙𝚕𝚎) выводит False True одной строкой.
Почему это важно
Один «лишний» символ, легко превращает значение в кортеж и ломает код далеко от места ошибки (например, при работе с dict, URL, числами), поэтому одноэлементные кортежи всегда лучше записывать явно как (𝚟𝚊𝚕𝚞𝚎,), а не полагаться на неочевидный синтаксис.
Развёрнутое пояснение
1️⃣Внутри тела класса 𝙰 создаётся атрибут 𝚡 = 𝟻.
2️⃣Затем начинается list comprehension [𝚡 𝚏𝚘𝚛 𝚒 𝚒𝚗 𝚛𝚊𝚗𝚐𝚎(𝟹)]; в Python 3 это выражение компилируется как отдельная вложенная функция со своей областью видимости.
3️⃣Итерируемый объект 𝚛𝚊𝚗𝚐𝚎(𝟹) вычисляется в области видимости класса (это работает), но выражение 𝚡 внутри comprehension ищется в локальной области comprehension, затем в глобальной — область класса пропускается.
4️⃣Поскольку 𝚡 не найден ни локально, ни глобально, выбрасывается NameError: name 'x' is not defined.
Почему это важно
Это неочевидное поведение часто ломает код при портировании с Python 2 на 3. Решение — вынести значение в итерируемое: [𝚡 𝚏𝚘𝚛 𝚡 𝚒𝚗 [𝚡] 𝚏𝚘𝚛 𝚒 𝚒𝚗 𝚛𝚊𝚗𝚐𝚎(𝟹)] или использовать значение по умолчанию в лямбде.
Развёрнутое пояснение
1️⃣Выражение 𝚊 = 𝚋 = [𝟷, 𝟸] вычисляет список один раз и присваивает ссылку на него обеим переменным 𝚊 и 𝚋 — они указывают на один и тот же объект.
2️⃣Вызов 𝚊.𝚊𝚙𝚙𝚎𝚗𝚍(𝟹) модифицирует этот список на месте: теперь он содержит [𝟷, 𝟸, 𝟹], и обе переменные видят это изменение.
3️⃣Выражение 𝚋 = 𝚋 + [𝟺] создаёт новый список из элементов 𝚋 плюс элемент 𝟺, и перепривязывает переменную 𝚋 к этому новому списку [𝟷, 𝟸, 𝟹, 𝟺]; переменная 𝚊 продолжает указывать на старый объект.
4️⃣Функция 𝚙𝚛𝚒𝚗𝚝(𝚊, 𝚋) выводит [1, 2, 3] [1, 2, 3, 4].
Почему это важно
Задача демонстрирует разницу между мутацией объекта (𝚊𝚙𝚙𝚎𝚗𝚍, +=) и созданием нового объекта (+). При цепочке присваиваний с изменяемыми объектами легко получить неожиданное разделение состояния между переменными.
Развёрнутое пояснение
1️⃣Глобальные 𝚐 = 𝟶 и 𝚗 = 𝟶.
2️⃣Вызывается 𝚘𝚞𝚝𝚎𝚛(): создаются локальные 𝚐 = 𝟷 и 𝚗 = 𝟷, которые перекрывают глобальные в этой области.
3️⃣В 𝚒𝚗𝚗𝚎𝚛 инструкция 𝚐𝚕𝚘𝚋𝚊𝚕 𝚐 привязывает 𝚐 к глобальной области (где 𝚐 = 𝟶), а 𝚗𝚘𝚗𝚕𝚘𝚌𝚊𝚕 𝚗 — к локальной 𝚗 из 𝚘𝚞𝚝𝚎𝚛.
4️⃣Присваивание 𝚐, 𝚗 = 𝟸, 𝟸: глобальная 𝚐 становится 𝟸, локальная 𝚗 из 𝚘𝚞𝚝𝚎𝚛 становится 𝟸. Локальная 𝚐 в 𝚘𝚞𝚝𝚎𝚛 остаётся 𝟷.
5️⃣𝚙𝚛𝚒𝚗𝚝(𝚐, 𝚗) внутри 𝚘𝚞𝚝𝚎𝚛 выводит локальную 𝚐 = 𝟷 и 𝚗 = 𝟸 → 1 2.
Почему это важно
Симметричная структура кода (обе переменные инициализируются одинаково на всех уровнях) создаёт иллюзию, что 𝚐𝚕𝚘𝚋𝚊𝚕 и 𝚗𝚘𝚗𝚕𝚘𝚌𝚊𝚕 работают одинаково — но 𝚐𝚕𝚘𝚋𝚊𝚕 игнорирует промежуточную область 𝚘𝚞𝚝𝚎𝚛, а 𝚗𝚘𝚗𝚕𝚘𝚌𝚊𝚕 работает именно с ней.
Развёрнутое пояснение
1️⃣Глобальная переменная 𝚡 получает значение 𝟷𝟶.
2️⃣При компиляции функции 𝚏𝚘𝚘 Python видит строку 𝚡 = 𝟸𝟶 и помечает 𝚡 как локальную переменную для всего тела функции.
3️⃣Когда функция вызывается и выполняется 𝚙𝚛𝚒𝚗𝚝(𝚡), Python ищет 𝚡 в локальной области видимости, но присваивание ещё не произошло — переменная существует, но не связана со значением.
4️⃣Выбрасывается UnboundLocalError: local variable 'x' referenced before assignment.
Почему это важно
Эта ошибка часто сбивает с толку начинающих: кажется, что глобальная переменная должна быть видна, но наличие присваивания ниже по коду «перетягивает» её в локальную область. Решение — либо использовать 𝚐𝚕𝚘𝚋𝚊𝚕 𝚡, либо не переиспользовать имя глобальной переменной.
Развёрнутое пояснение
1️⃣Вызов 𝚜𝚞𝚖(𝚒𝚝𝚎𝚛𝚊𝚋𝚕𝚎, 𝚜𝚝𝚊𝚛𝚝) эквивалентен последовательному сложению: 𝚜𝚝𝚊𝚛𝚝 + 𝚒𝚝𝚎𝚖𝟷 + 𝚒𝚝𝚎𝚖𝟸 + ....
2️⃣Здесь 𝚜𝚝𝚊𝚛𝚝 = [] (пустой список), а элементы итерируемого — [𝟷, 𝟸] и [𝟹, 𝟺].
3️⃣Первый шаг: [] + [𝟷, 𝟸] → [𝟷, 𝟸].
4️⃣Второй шаг: [𝟷, 𝟸] + [𝟹, 𝟺] → [𝟷, 𝟸, 𝟹, 𝟺].
5️⃣Переменная 𝚛𝚎𝚜𝚞𝚕𝚝 получает этот список, и print выводит [1, 2, 3, 4].
Почему это важно
Это «хакерский» способ сгладить список списков, но он неэффективен (квадратичная сложность из-за создания промежуточных списков); для реальных задач лучше использовать 𝚒𝚝𝚎𝚛𝚝𝚘𝚘𝚕𝚜.𝚌𝚑𝚊𝚒𝚗.𝚏𝚛𝚘𝚖_𝚒𝚝𝚎𝚛𝚊𝚋𝚕𝚎() или list comprehension.
