ru
Feedback
Python: задачки и вопросы

Python: задачки и вопросы

Открыть в Telegram

Вопросы и задачки для подготовки к собеседованиям и прокачки навыков Разместить рекламу: @tproger_sales_bot Правила общения: https://tprg.ru/rules Другие каналы: @tproger_channels Другие наши проекты: https://tprg.ru/media

Больше
6 963
Подписчики
+124 часа
-67 дней
-6130 день
Архив постов
Что выведет код?
Anonymous voting

photo content

Учитесь новому так, как удобно вам, вместе с Академией Топ Академия Топ — это крупнейшая образовательная сеть с филиалами в 230 городах, в которой вы можете изучать множество разнообразных IT-профессий. По итогам обучения выпускники Академии получают государственный диплом, признанный в 7 странах мира. Выбирайте курс по душе: • «Разработка на Python»«Разработчик программного обеспечения»«Кибербезопасность и сетевые технологии» • и многое другое Академия регулярно проводит бесплатные дни открытых дверей «Старт в IT» для тех, кто мечтает о карьере в IT, но не знает, с чего начать. Вы сможете познакомиться с преподавателями, получить индивидуальную консультацию, увидеть работы студентов и посетить экскурсию по Академии. А для тех, кто уже выбрал своим направлением Python-разработку, в Академии Топ проводят пробные занятия «Python с нуля: создаём чат-бота», где вы на практике изучите основы универсального языка программирования и создадите свой первый проект. Выбирайте свой курс с подходящим вам форматом обучения! Реклама. Филиал «АКАДЕМИЯ ТОП КУТУЗОВСКИЙ», ИНН 7730257499, erid: 2W5zFK5c4jS

Развёрнутое пояснение 1️⃣Переменная 𝚝 указывает на кортеж с одним элементом — списком [𝟷, 𝟸]; сам кортеж неизменяем, но список внутри него — изменяемый объект. 2️⃣Выражение t[0] += [3] разворачивается примерно в t[0] = t[0].__iadd__([3]): сначала вызывается метод __iadd__ у списка, который добавляет элемент 𝟹 на месте и возвращает тот же самый изменённый список. 3️⃣Затем интерпретатор пытается выполнить присваивание t[0] = ..., но кортеж не поддерживает присваивание элементов, поэтому выбрасывается TypeError: 'tuple' object does not support item assignment. 4️⃣Однако к моменту исключения список уже был изменён методом __iadd__, поэтому если после ошибки проверить значение 𝚝, оно будет ([1, 2, 3],) — мутация произошла, несмотря на ошибку. Почему это важно Задача показывает, что составные операторы вроде += — это не атомарная операция, а последовательность из нескольких шагов, и сбой на одном из них не откатывает предыдущие. Это учит быть осторожнее при работе с вложенными изменяемыми объектами внутри неизменяемых контейнеров и помнить, что «неизменяемость» кортежа распространяется только на его структуру, а не на содержимое элементов.

Что выведет код?
Anonymous voting

Разбираем по шагам: 1️⃣В выражении True == 1 используется оператор равенства: булевый тип 𝚋𝚘𝚘𝚕 является подклассом 𝚒𝚗𝚝, и значение True ведёт себя как единица, поэтому результат сравнения — логическое True, и переменная 𝚊 получает значение True.​ 2️⃣Во второй строке 1 == True просто меняет местами операнды, но семантика == остаётся прежней: значения всё так же считаются равными, поэтому переменная 𝚋 тоже становится True.​ 3️⃣В третьей строке вызывается type(True) — результатом будет объект типа 𝚋𝚘𝚘𝚕, и type(1) — объект типа 𝚒𝚗𝚝; оператор is здесь проверяет, являются ли оба результата вызова type(...) одним и тем же объектом типа, и так как 𝚋𝚘𝚘𝚕 и 𝚒𝚗𝚝 — разные классы, выражение даёт False, поэтому 𝚌 получает False.​ 4️⃣При вызове print(a, b, c) функция печатает текущие значения 𝚊, 𝚋 и 𝚌 через пробел, что даёт строку True True False. Эта задачка важна тем, что показывает: булевы значения в Python — это не магический отдельный тип, а вполне себе подкласс целых чисел, поэтому True, 1 и 1.0 могут неожиданно сливаться в один и тот же ключ словаря или проходить проверки типов там, где ожидается int.

Что выведет код?
Anonymous voting

По шагам: 1️⃣На первой строке создаётся пустой список 𝚡 = []. Пустые коллекции в Python имеют ложное булево значение, то есть 𝚋𝚘𝚘𝚕(𝚡) = 𝙵𝚊𝚕𝚜𝚎.​ 2️⃣Выражение 𝚢 = 𝚡 𝚘𝚛 [𝟷, 𝟸] работает по правилу: оператор 𝚘𝚛 возвращает первый операнд, если он истинный, иначе второй. Так как 𝚡 — пустой список (ложное значение), результатом становится второй операнд — список [𝟷, 𝟸], и именно он присваивается переменной 𝚢.​ 3️⃣Далее вычисляется 𝚣 = 𝚡 𝚊𝚗𝚍 [𝟹, 𝟺]. Для 𝚊𝚗𝚍 правило обратное: возвращается первый ложный операнд, а если оба истинные — второй. Поскольку 𝚡 — ложное значение, короткое замыкание срабатывает сразу, второй операнд не вычисляется, и в 𝚣 попадает тот же пустой список [].​ 4️⃣Вызов 𝚙𝚛𝚒𝚗𝚝(𝚢, 𝚣) печатает строковое представление двух объектов через пробел: сначала список [𝟷, 𝟸] как [1, 2], затем пустой список как [], поэтому итоговая и единственная строка вывода — [1, 2] [].​ Чему нас учит эта задачка: логические операторы 𝚊𝚗𝚍 и 𝚘𝚛 в Python возвращают один из операндов, а не обязательно булево значение, и активно используют правду/ложь контейнеров (пустой список, пустая строка и т.п.), что полезно и для удобного задания дефолтных значений, и для лаконичных проверок.

Что выведет код?
Anonymous voting

photo content

По шагам: 1️⃣В начале вызывается функция 𝚏𝚘𝚘, внутри создаётся список 𝚗𝚞𝚖𝚜 = [𝟷, 𝟸, 𝟹]. 2️⃣В блоке 𝚝𝚛𝚢 запускается цикл 𝚏𝚘𝚛 𝚒 𝚒𝚗 𝚛𝚊𝚗𝚐𝚎(𝚕𝚎𝚗(𝚗𝚞𝚖𝚜)), переменная 𝚒 по очереди принимает значения 𝟶, 𝟷, 𝟸. 3️⃣При 𝚒 = 𝟶 условие 𝚒 == 𝟷 ложно, выполняется умножение 𝚗𝚞𝚖𝚜[𝟶] = 𝚗𝚞𝚖𝚜[𝟶] * 𝟷𝟶, и список становится [𝟷𝟶, 𝟸, 𝟹]. 4️⃣При 𝚒 = 𝟷 условие 𝚒 == 𝟷 истинно, выполняется 𝚛𝚊𝚒𝚜𝚎 𝚅𝚊𝚕𝚞𝚎𝙴𝚛𝚛𝚘𝚛(𝚍𝚊𝚝𝚊), до строки с умножением элемента список уже не доходит, поэтому элементы с индексами 𝟷 и 𝟸 остаются как были: [𝟷𝟶, 𝟸, 𝟹]. 5️⃣Исключение перехватывается в блоке 𝚎𝚡𝚌𝚎𝚙𝚝 𝚅𝚊𝚕𝚞𝚎𝙴𝚛𝚛𝚘𝚛, там подготавливается к возврату кортеж ("error", 𝚗𝚞𝚖𝚜), но фактический выход из функции откладывается до завершения блока 𝚏𝚒𝚗𝚊𝚕𝚕𝚢. 6️⃣В блоке 𝚏𝚒𝚗𝚊𝚕𝚕𝚢 в тот же объект списка 𝚗𝚞𝚖𝚜 добавляется элемент 𝟿𝟿 через вызов 𝚗𝚞𝚖𝚜.𝚊𝚙𝚙𝚎𝚗𝚍(𝟿𝟿), и список становится [𝟷𝟶, 𝟸, 𝟹, 𝟿𝟿]. 7️⃣Затем вызывается 𝚙𝚛𝚒𝚗𝚝(𝚗𝚞𝚖𝚜), в стандартный вывод уходит единственная строка с представлением списка [𝟷𝟶, 𝟸, 𝟹, 𝟿𝟿], а возвращаемое значение функции 𝚏𝚘𝚘 нигде не используется. Из этой задачи видно, что блок 𝚏𝚒𝚗𝚊𝚕𝚕𝚢 всегда выполняется при выходе из 𝚝𝚛𝚢/𝚎𝚡𝚌𝚎𝚙𝚝, даже если уже выбран результат 𝚛𝚎𝚝𝚞𝚛𝚗 или поймано исключение, и может ещё изменить состояние объектов. Мы также чётко видим, что работа с изменяемыми структурами данных внутри 𝚏𝚒𝚗𝚊𝚕𝚕𝚢 напрямую влияет на то, что попадёт в вывод или вернётся из функции, поэтому такие побочные эффекты лучше держать под контролем и не недооценивать их.

Что выведет код?
Anonymous voting

photo content

Разбор по шагам 1️⃣Декоратор @𝚙𝚛𝚘𝚙𝚎𝚛𝚝𝚢 создаёт объект дескриптора, который хранит функцию 𝚗𝚊𝚖𝚎. Этот объект дескриптор помещается в словарь класса 𝚄𝚜𝚎𝚛.𝚍𝚒𝚌𝚝 под именем 𝚗𝚊𝚖𝚎. ​ 2️⃣Выражение 𝚄𝚜𝚎𝚛.𝚗𝚊𝚖𝚎 — это обращение к атрибуту через класс (без создания экземпляра). Python находит дескриптор, но поскольку обращение идёт не через экземпляр, дескриптор просто возвращает сам себя — объект 𝚙𝚛𝚘𝚙𝚎𝚛𝚝𝚢. Первый 𝚙𝚛𝚒𝚗𝚝 выводит что‑то вроде <𝚙𝚛𝚘𝚙𝚎𝚛𝚝𝚢 𝚘𝚋𝚓𝚎𝚌𝚝 𝚊𝚝 𝟶𝚡...>.​ 3️⃣Выражение 𝚄𝚜𝚎𝚛() создаёт новый экземпляр класса 𝚄𝚜𝚎𝚛. 4️⃣Обращение .𝚗𝚊𝚖𝚎 на этом экземпляре заставляет дескриптор сработать: он вызывает сохранённую функцию 𝚗𝚊𝚖𝚎(𝚜𝚎𝚕𝚏) и возвращает её результат «𝚒𝚗𝚜𝚝𝚊𝚗𝚌𝚎».​ 5️⃣Второй 𝚙𝚛𝚒𝚗𝚝 выводит строку «𝚒𝚗𝚜𝚝𝚊𝚗𝚌𝚎». Когда интерпретатор видит метод с декоратором 𝚙𝚛𝚘𝚙𝚎𝚛𝚝𝚢, он примерно делает так:​ 🔘берёт функцию 𝚏𝚞𝚗𝚌 = 𝚄𝚜𝚎𝚛.𝚗𝚊𝚖𝚎; 🔘создаёт объект 𝚙𝚛𝚘𝚙 = 𝚙𝚛𝚘𝚙𝚎𝚛𝚝𝚢(𝚏𝚞𝚗𝚌); 🔘кладёт его в класс: в 𝚄𝚜𝚎𝚛.𝚍𝚒𝚌𝚝 под ключом 𝚗𝚊𝚖𝚎 теперь лежит не функция, а объект 𝚙𝚛𝚘𝚙𝚎𝚛𝚝𝚢.​ Класс 𝚙𝚛𝚘𝚙𝚎𝚛𝚝𝚢 сам по себе — обычный класс, у которого реализованы методы 𝚐𝚎𝚝, 𝚜𝚎𝚝, 𝚍𝚎𝚕𝚎𝚝𝚎. Это и называют дескриптором.​ Благодаря такому устройству 🔘можно писать 𝚞𝚜𝚎𝚛.𝚊𝚐𝚎 вместо 𝚞𝚜𝚎𝚛.𝚐𝚎𝚝_𝚊𝚐𝚎(), а под капотом при этом выполняется логика (валидация, преобразования, кэширование и т. п.);​ 🔘можно сперва сделать обычное поле 𝚞𝚜𝚎𝚛.𝚊𝚐𝚎, а позже заменить его на вычисляемое свойство, не ломая код, который его читает — внешний интерфейс (𝚞𝚜𝚎𝚛.𝚊𝚐𝚎) не меняется.

Что выведет код?
Anonymous voting

photo content

1️⃣Определены функции 𝚏𝚎𝚝𝚌𝚑 и 𝚖𝚊𝚒𝚗, но они ничего не делают сами по себе, пока не будут запущены через await/цикл событий. 2️⃣Строка 𝚌𝚘𝚛𝚘 = 𝚖𝚊𝚒𝚗() создаёт объект‑корутину 𝚌𝚘𝚛𝚘; тело 𝚖𝚊𝚒𝚗 (и, следовательно, 𝚏𝚎𝚌𝚝𝚌𝚑) при этом не исполняется.​ 3️⃣Вызов 𝚌𝚘𝚛𝚘.𝚌𝚕𝚘𝚜𝚎() корректно завершает корутину, что предотвращает предупреждение «coroutine was never awaited»; метод 𝚌𝚕𝚘𝚜𝚎 доступен у корутин по спецификации.​ 4️⃣Поскольку ни 𝚖𝚊𝚒𝚗, ни 𝚏𝚎𝚌𝚑 не выполнялись, строки "fetching" и "done" не печатаются; затем исполняется обычный синхронный 𝚙𝚛𝚒𝚗𝚝("after") и выводит единственную строку. Как работает async/await Асинхронное программирование позволяет программе не простаивать во время долгих операций (сеть, диск, база данных). Ключевое слово 𝚊𝚜𝚢𝚗𝚌 превращает функцию в корутину — объект, который можно «приостановить» на await и потом продолжить, при этом цикл событий в момент ожидания переключается на другие задачи. Для реального запуска корутины нужен либо 𝚊𝚠𝚊𝚒𝚝 внутри другой async‑функции, либо явный вызов через 𝚊𝚜𝚢𝚗𝚌𝚒𝚘.𝚛𝚞𝚗() или цикл событий.​ Подробнее про основы асинхронности в Python и чуть глубже о том, почему мало кто на самом деле понимает как это работает.

Что выведет код?
Anonymous voting