Python: задачки и вопросы
7.2K subscribers
1.34K photos
1 video
1 file
122 links
Вопросы и задачки для подготовки к собеседованиям и прокачки навыков

Разместить рекламу: @tproger_sales_bot

Правила общения: https://tprg.ru/rules

Другие каналы: @tproger_channels

Другие наши проекты: https://tprg.ru/media
Download Telegram
Развёрнутое пояснение

1️⃣Внутри блока 𝚎𝚡𝚌𝚎𝚙𝚝 создаются две переменные: 𝚎 (алиас исключения) и 𝚖𝚜𝚐 (обычная строка).

2️⃣По спецификации Python, 𝚎𝚡𝚌𝚎𝚙𝚝 ... 𝚊𝚜 𝚎 неявно выполняет 𝚍𝚎𝚕 𝚎 при выходе из блока. Это сделано потому, что объект исключения хранит ссылку на traceback, который ссылается на все локальные переменные фрейма — без удаления возникнет утечка памяти.

3️⃣Переменная 𝚖𝚜𝚐 — обычная строка, она не удаляется и доступна после блока.

4️⃣𝚙𝚛𝚒𝚗𝚝(𝚖𝚜𝚐) срабатывает, а вот второй, а 𝚙𝚛𝚒𝚗𝚝(e) при обращении к 𝚎 выбрасывает NameError.

Почему это важно
Если нужно сохранить исключение для использования после блока 𝚎𝚡𝚌𝚎𝚙𝚝, его нужно явно присвоить другой переменной (как 𝚖𝚜𝚐 в примере). Иначе код упадёт в неожиданном месте.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Что выведет код?
Anonymous Quiz
40%
10 10
46%
10 8
8%
8 8
6%
8 10
👍3
Развёрнутое пояснение

1️⃣𝚒𝚗𝚝("𝟶𝟷𝟶") вызывается без второго аргумента, значит основание — 𝟷𝟶. Строка "𝟶𝟷𝟶" парсится как десятичное число, ведущий ноль не имеет значения. Результат: 𝟷𝟶.

2️⃣Литерал 𝟶𝚘𝟷𝟶 в Python — это восьмеричная запись: 𝟷 × 𝟾 + 𝟶 = 𝟾.

3️⃣В Python 2 запись 𝟶𝟷𝟶 без буквы 𝚘 тоже была восьмеричной, что вызывало путаницу. В Python 3 это запретили: 𝟶𝟷𝟶 как литерал — это SyntaxError, нужно писать 𝟶𝚘𝟷𝟶.

4️⃣Но 𝚒𝚗𝚝("𝟶𝟷𝟶") — это парсинг строки, и тут ведущий ноль просто пропускается.

Почему это важно
При парсинге данных из файлов или API числа вроде "010" могут означать и десятичное 𝟷𝟶, и восьмеричное 𝟾 — зависит от контекста. Если нужен восьмеричный парсинг, пишите 𝚒𝚗𝚝("𝟶𝟷𝟶", 𝟾) явно.
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1
Что выведет код?
Anonymous Quiz
15%
1 2
7%
0 1
74%
1 1
4%
Error
👍2
Развёрнутое пояснение

1️⃣Начальные значения: 𝚊 = 𝟶, 𝚋 = 𝟷.

2️⃣Выражение 𝚊, 𝚋 = 𝚋, 𝚊 + 𝚋 сначала вычисляет правую часть как кортеж: (𝚋, 𝚊 + 𝚋) → (𝟷, 𝟶 + 𝟷) → (𝟷, 𝟷).

3️⃣Только после этого значения распаковываются: 𝚊 = 𝟷, 𝚋 = 𝟷.

4️⃣Можно ожидать, что 𝚋 = 𝟸, думая, что сначала 𝚊 станет 𝟷, а потом 𝚊 + 𝚋 = 𝟷 + 𝟷 = 𝟸. Но нет — правая часть вычисляется со старыми значениями.

Почему это важно
Это то, что делает 𝚊, 𝚋 = 𝚋, 𝚊 безопасным свопом без временной переменной. Но в более сложных выражениях, как здесь (числа Фибоначчи), легко неправильно предсказать результат, если не помнить это правило.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Что выведет код?
Anonymous Quiz
33%
True
18%
False
18%
check True
23%
check False
8%
Error
👍4
Развёрнутое пояснение

1️⃣Список [𝚃𝚛𝚞𝚎, 𝚙𝚛𝚒𝚗𝚝("𝚌𝚑𝚎𝚌𝚔", 𝚎𝚗𝚍=" "), 𝚃𝚛𝚞𝚎] вычисляется слева направо при создании.

2️⃣Вызов 𝚙𝚛𝚒𝚗𝚝("𝚌𝚑𝚎𝚌𝚔", 𝚎𝚗𝚍=" ") печатает check (с пробелом вместо переноса строки) и возвращает 𝙽𝚘𝚗𝚎 — все функции без явного 𝚛𝚎𝚝𝚞𝚛𝚗 возвращают 𝙽𝚘𝚗𝚎.

3️⃣Список превращается в [𝚃𝚛𝚞𝚎, 𝙽𝚘𝚗𝚎, 𝚃𝚛𝚞𝚎].

4️⃣Функция 𝚊𝚕𝚕() проверяет истинность всех элементов. Первый элемент 𝚃𝚛𝚞𝚎 — истинный, второй 𝙽𝚘𝚗𝚎 — ложный, поэтому 𝚊𝚕𝚕() сразу возвращает False.

5️⃣Переменная 𝚛𝚎𝚜𝚞𝚕𝚝 получает False, и печатается check (из 𝚙𝚛𝚒𝚗𝚝), а затем False.

Почему это важно
Встраивание функций с побочными эффектами в проверки 𝚊𝚕𝚕() или 𝚊𝚗𝚢() может давать неожиданный результат, если функция возвращает 𝙽𝚘𝚗𝚎 или другое falsy-значение.
Please open Telegram to view this post
VIEW IN TELEGRAM
3
Что выведет код?
Anonymous Quiz
43%
True
21%
False
3%
None
33%
Error
👍1👀1
Развёрнутое пояснение

1️⃣𝚏𝚕𝚘𝚊𝚝("𝚒𝚗𝚏") создаёт положительную бесконечность — специальное значение, большее любого конечного числа.

2️⃣Операция 𝚡 + 𝟷 пытается прибавить 𝟷 к бесконечности. По правилам IEEE 754, ∞ + 𝚗 = ∞ для любого конечного 𝚗.

3️⃣Результат снова 𝚏𝚕𝚘𝚊𝚝("𝚒𝚗𝚏"), и сравнение 𝚏𝚕𝚘𝚊𝚝("𝚒𝚗𝚏") == 𝚏𝚕𝚘𝚊𝚝("𝚒𝚗𝚏") даёт True.

4️⃣То же самое для умножения, вычитания конечного числа: 𝚒𝚗𝚏 * 𝟸 = 𝚒𝚗𝚏, 𝚒𝚗𝚏 - 𝟷𝟶𝟶𝟶 = 𝚒𝚗𝚏.

Почему это важно
Бесконечность используют для инициализации минимумов/максимумов: 𝚖𝚒𝚗_𝚟𝚊𝚕 = 𝚏𝚕𝚘𝚊𝚝("𝚒𝚗𝚏"). Но арифметика с ней нетривиальна: 𝚒𝚗𝚏 - 𝚒𝚗𝚏 = 𝙽𝚊𝙽, а деление на 𝚒𝚗𝚏 даёт 𝟶. Это может сломать логику, если не учитывать особые случаи.
Please open Telegram to view this post
VIEW IN TELEGRAM
42
Развёрнутое пояснение

1️⃣Генератор 𝚐 создаёт последовательность из двух элементов: 𝟶 и 𝟷.

2️⃣Первый 𝚗𝚎𝚡𝚝(𝚐, "𝚎𝚖𝚙𝚝𝚢") извлекает 𝟶, переменная 𝚊 = 𝟶.

3️⃣Второй 𝚗𝚎𝚡𝚝(𝚐, "𝚎𝚖𝚙𝚝𝚢") извлекает 𝟷, переменная 𝚋 = 𝟷.

4️⃣Третий вызов 𝚗𝚎𝚡𝚝(𝚐, "𝚎𝚖𝚙𝚝𝚢"): генератор исчерпан, но передан второй аргумент — default-значение. Вместо исключения StopIteration возвращается "𝚎𝚖𝚙𝚝𝚢", переменная 𝚌 = "𝚎𝚖𝚙𝚝𝚢".

5️⃣Если бы был просто 𝚗𝚎𝚡𝚝(𝚐) без второго аргумента, выбросилось бы StopIteration.

Почему это важно
Это полезный паттерн для безопасной работы с итераторами неизвестной длины: 𝚗𝚎𝚡𝚝(𝚒𝚝𝚎𝚛𝚊𝚝𝚘𝚛, 𝙽𝚘𝚗𝚎) или 𝚗𝚎𝚡𝚝(𝚒𝚝𝚎𝚛𝚊𝚝𝚘𝚛, 𝚍𝚎𝚏𝚊𝚞𝚕𝚝_𝚟𝚊𝚕𝚞𝚎) позволяет избежать обработки исключений.
Please open Telegram to view this post
VIEW IN TELEGRAM
3
Что выведет код?
Anonymous Quiz
37%
hello
10%
Hello
51%
HELLO
1%
Error
🤔32🥰2