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

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

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

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

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

1️⃣Выражение 𝚊 = 𝚋 = [𝟷, 𝟸] вычисляет список один раз и присваивает ссылку на него обеим переменным 𝚊 и 𝚋 — они указывают на один и тот же объект.​

2️⃣Вызов 𝚊.𝚊𝚙𝚙𝚎𝚗𝚍(𝟹) модифицирует этот список на месте: теперь он содержит [𝟷, 𝟸, 𝟹], и обе переменные видят это изменение.

3️⃣Выражение 𝚋 = 𝚋 + [𝟺] создаёт новый список из элементов 𝚋 плюс элемент 𝟺, и перепривязывает переменную 𝚋 к этому новому списку [𝟷, 𝟸, 𝟹, 𝟺]; переменная 𝚊 продолжает указывать на старый объект.​

4️⃣Функция 𝚙𝚛𝚒𝚗𝚝(𝚊, 𝚋) выводит [1, 2, 3] [1, 2, 3, 4].

Почему это важно
Задача демонстрирует разницу между мутацией объекта (𝚊𝚙𝚙𝚎𝚗𝚍, +=) и созданием нового объекта (+). При цепочке присваиваний с изменяемыми объектами легко получить неожиданное разделение состояния между переменными.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Что выведет код в Python 3?
Anonymous Quiz
50%
[5, 5, 5]
23%
[0, 1, 2]
19%
NameError
8%
SyntaxError
Развёрнутое пояснение

1️⃣Внутри тела класса 𝙰 создаётся атрибут 𝚡 = 𝟻.

2️⃣Затем начинается list comprehension [𝚡 𝚏𝚘𝚛 𝚒 𝚒𝚗 𝚛𝚊𝚗𝚐𝚎(𝟹)]; в Python 3 это выражение компилируется как отдельная вложенная функция со своей областью видимости.

3️⃣Итерируемый объект 𝚛𝚊𝚗𝚐𝚎(𝟹) вычисляется в области видимости класса (это работает), но выражение 𝚡 внутри comprehension ищется в локальной области comprehension, затем в глобальной — область класса пропускается.

4️⃣Поскольку 𝚡 не найден ни локально, ни глобально, выбрасывается NameError: name 'x' is not defined.

Почему это важно
Это неочевидное поведение часто ломает код при портировании с Python 2 на 3. Решение — вынести значение в итерируемое: [𝚡 𝚏𝚘𝚛 𝚡 𝚒𝚗 [𝚡] 𝚏𝚘𝚛 𝚒 𝚒𝚗 𝚛𝚊𝚗𝚐𝚎(𝟹)] или использовать значение по умолчанию в лямбде.
Please open Telegram to view this post
VIEW IN TELEGRAM
🙈2👍1
Развёрнутое пояснение

1️⃣Переменной 𝚊 присваивается целое число 𝟷.

2️⃣В выражении 𝚋 = (𝚊) скобки играют только роль группировки — результатом остаётся то же значение 𝟷, и 𝚋 ссылается на обычное целое; поэтому 𝚝𝚢𝚙𝚎(𝚋) 𝚒𝚜 𝚝𝚞𝚙𝚕𝚎 возвращает False.

3️⃣В выражении 𝚌 = (𝚊,) уже есть запятая, которая и создаёт одноэлементный кортеж; поэтому 𝚝𝚢𝚙𝚎(𝚌) 𝚒𝚜 𝚝𝚞𝚙𝚕𝚎 даёт True.

4️⃣Функция 𝚙𝚛𝚒𝚗𝚝(𝚝𝚢𝚙𝚎(𝚋) 𝚒𝚜 𝚝𝚞𝚙𝚕𝚎, 𝚝𝚢𝚙𝚎(𝚌) 𝚒𝚜 𝚝𝚞𝚙𝚕𝚎) выводит False True одной строкой.

Почему это важно

Один «лишний» символ, легко превращает значение в кортеж и ломает код далеко от места ошибки (например, при работе с dict, URL, числами), поэтому одноэлементные кортежи всегда лучше записывать явно как (𝚟𝚊𝚕𝚞𝚎,), а не полагаться на неочевидный синтаксис.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Развёрнутое пояснение

1️⃣Создаётся список 𝚗𝚞𝚖𝚜 = [𝟷, 𝟸, 𝟹], переменная 𝚊 получает ссылку на тот же самый объект: и 𝚊, и 𝚗𝚞𝚖𝚜 указывают на один список.

2️⃣Выражение 𝚗𝚞𝚖𝚜[:] = [𝟺, 𝟻] — это именно срезовое присваивание: левая часть берёт весь список как срез, а правая заменяет его содержимое элементами из нового списка.

3️⃣В результате исходный объект списка переписывается на [𝟺, 𝟻], но ссылка 𝚊 по‑прежнему указывает на него же, так что и 𝚊, и 𝚗𝚞𝚖𝚜 теперь содержат один и тот же список [𝟺, 𝟻].

4️⃣𝚙𝚛𝚒𝚗𝚝(𝚊, 𝚗𝚞𝚖𝚜) печатает [4, 5] [4, 5].

Почему это важно
Потом что [:] = — это не то же самое, что простое =, и любое незаметное срезовое присваивание может поменять список, который уже разделяют несколько переменных или даже разные части кода.
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Весь год вы носили футболки и джинсы… Хватит!

Заглядывайте к нам в виртуальную примерочную и выбирайте себе идеальный скин для встречи Нового года!

Делитесь в комментариях, какой скин вам выпал 👀
🎉2
Развёрнутое пояснение

1️⃣При определении класса 𝙱𝚘𝚡 создаётся атрибут класса 𝚒𝚝𝚎𝚖𝚜 и привязывается к пустому списку []; этот список один на весь класс, а не на экземпляр.

2️⃣В конструкторе __init__ обращение 𝚜𝚎𝚕𝚏.𝚒𝚝𝚎𝚖𝚜 находит этот атрибут класса (у экземпляра ещё нет своего 𝚒𝚝𝚎𝚖𝚜) и вызывает у него метод 𝚊𝚙𝚙𝚎𝚗𝚍.

3️⃣Создание 𝚊 = 𝙱𝚘𝚡(𝟷) добавляет 𝟷 в общий список → теперь 𝚒𝚝𝚎𝚖𝚜 = [𝟷]. Создание 𝚋 = 𝙱𝚘𝚡(𝟸) добавляет 𝟸 в тот же самый список → [𝟷, 𝟸].

4️⃣И 𝚊.𝚒𝚝𝚎𝚖𝚜, и 𝚋.𝚒𝚝𝚎𝚖𝚜 ссылаются на один и тот же общий список, поэтому print(a.items, b.items) выводит [1, 2] [1, 2].

Почему это важно
Общий изменяемый атрибут класса легко превращается в неявный «shared state» между инстансами и рождает трудноуловимые баги; если список должен быть отдельным у каждого объекта, его нужно создавать в __init__ как 𝚜𝚎𝚕𝚏.𝚒𝚝𝚎𝚖𝚜 = [].
Please open Telegram to view this post
VIEW IN TELEGRAM
5
Что выведет код?
Anonymous Quiz
46%
[]
6%
[2, 4, 6, 8]
30%
[4, 8]
18%
Error
🤝41
Развёрнутое пояснение

🔘Список 𝚗𝚞𝚖𝚜 = [𝟸, 𝟺, 𝟼, 𝟾]. Цикл использует внутренний индекс, который увеличивается на каждой итерации.

0️⃣Шаг 𝟶: индекс 𝟶, элемент 𝟸, условие истинно, вызывается 𝚗𝚞𝚖𝚜.𝚛𝚎𝚖𝚘𝚟𝚎(𝟸). Список становится [𝟺, 𝟼, 𝟾], но индекс уже переходит к 𝟷.

1️⃣Шаг 𝟷: индекс 𝟷, в списке [𝟺, 𝟼, 𝟾] это элемент 𝟼 (а не 𝟺!), условие истинно, удаляем 𝟼. Список становится [𝟺, 𝟾], индекс переходит к 𝟸.

2️⃣Шаг 𝟸: индекс 𝟸 выходит за пределы списка длины 𝟸, цикл завершается.

3️⃣Элементы 𝟺 и 𝟾 никогда не были проверены, потому что итератор их «перепрыгнул». Результат: [𝟺, 𝟾].

Почему это важно
Задача наглядно показывает, почему нельзя удалять элементы из списка во время итерации по нему: даже если кажется, что «всё должно удалиться», половина элементов останется. Безопасные альтернативы: итерация по копии 𝚏𝚘𝚛 𝚡 𝚒𝚗 𝚗𝚞𝚖𝚜[:], list comprehension [𝚡 𝚏𝚘𝚛 𝚡 𝚒𝚗 𝚗𝚞𝚖𝚜 𝚒𝚏 𝚡 % 𝟸 != 𝟶], или проход в обратном порядке.
Please open Telegram to view this post
VIEW IN TELEGRAM
11
Развёрнутое пояснение

1️⃣В словаре 𝚍 два ключа: 𝟷 и 𝟸; соответствующие значения — "𝚘𝚗𝚎" и "𝚝𝚠𝚘".

2️⃣Выражение 𝟷 𝚒𝚗 𝚍 проверяет наличие 𝟷 среди ключей словаря; такой ключ есть, поэтому результат — True.

3️⃣Выражение "𝚘𝚗𝚎" 𝚒𝚗 𝚍 тоже смотрит только на ключи: строка "𝚘𝚗𝚎" не является ключом, это значение; поэтому результат — False.

4️⃣Функция 𝚙𝚛𝚒𝚗𝚝(𝟷 𝚒𝚗 𝚍, "𝚘𝚗𝚎" 𝚒𝚗 𝚍) выводит True False.

Почему это важно
Путаница между проверкой по ключам и по значениям часто ломает валидацию и условия: чтобы искать по значениям, нужно явно использовать "𝚘𝚗𝚎" 𝚒𝚗 𝚍.𝚟𝚊𝚕𝚞𝚎𝚜() или итерироваться по парам, а не надеяться на поведение по умолчанию.
Please open Telegram to view this post
VIEW IN TELEGRAM