December 9, 2024

Python: Средний уровень. Теоретическое задание

В этой статье мы разберем тестовые задания среднего уровня по Python, состоящего из:

  1. Теоретической части – основные вопросы, которые могут встретиться, и как правильно на них отвечать.
  2. Практической части – решение практического задания с детальным разбором, рассмотрено в статье Python: Средний уровень. Практическое задание

Вопрос 1:

Какой результат будет выведен после применения операции 3 * '5'?

Варианты ответа:

  1. ['5', '5', '5']
  2. 15
  3. Ошибка TypeError
  4. '35'
  5. '555'

Обоснование: В Python оператор умножения (*) ведёт себя по-разному в зависимости от типов операндов:

  • Если оба операнда — числа, производится математическое умножение.
  • Если один из операндов является строкой, а другой целым числом (int), то строка повторяется указанное количество раз. Например, '5' * 3 создаст строку '555'.

В данном случае '5' — строка, а 3 — целое число. Результат операции 3 * '5' — повторение строки '5' три раза, что даёт строку '555'.

📌Правильный ответ: 5. '555'

Вопрос 2:

В вашем проекте необходимо хранить состояние различных процессов, таких как «запущен», «приостановлен» и «остановлен». Какой тип данных лучше всего подходит для хранения этих состояний?

Варианты ответа:

  1. Множество (set)
  2. Список (list)
  3. Класс enum.Enum
  4. Кортеж (tuple)
  5. Словарь (dict)

Обоснование: Для хранения фиксированного набора состояний, таких как «запущен», «приостановлен» и «остановлен», важно использовать структуру данных, которая:

  • Является статичной и содержит заранее определённые значения.
  • Позволяет однозначно ассоциировать состояние с конкретным процессом.
  • Обеспечивает читаемость и поддержку в коде.

Наиболее подходящим вариантом является использование класса enum.Enum, так как:

  • Он позволяет задать фиксированный набор состояний.
  • Состояния представлены в виде атрибутов, что повышает читаемость и предотвращает ошибки (например, опечатки).
  • enum.Enum поддерживает сравнение значений и прост в интеграции с другими частями кода.

Другие варианты менее эффективны:

  • Множество (set): Не фиксирует порядок, и значения могут быть случайно добавлены/удалены, что не подходит для фиксированных состояний.
  • Список (list): Поддерживает порядок, но не защищает от дублирования и случайных изменений.
  • Кортеж (tuple): Фиксированный набор значений, но не предоставляет контекста для работы с состояниями.
  • Словарь (dict): Нужен для работы с парами ключ-значение, что избыточно для простого набора состояний.

📌Правильный ответ: 3. Класс enum.Enum

Вопрос 3:

Вы пишете функцию для рекомендации пробежки в зависимости от погодных условий — наличия дождя и температуры воздуха. Следующий код выводит результат «Идеально для пробежки». Что должно находиться на месте пропусков?

Варианты ответа:

  1. if is_raining: в первом случае и elif temperature >= 5 and temperature <= 15: во втором
  2. while is_raining == True: в первом случае и and elif temperature <= 15: во втором
  3. if is_raining == True: в первом случае и elif temperature >= 5 and <= 15:
  4. while is_raining: в первом случае и elif temperature >= 5 and <= 15: во втором
  5. if raining_status == True: в первом случае и elif temperature_status <= 15: во втором

Обоснование: Для корректной работы функции run_rec, которая определяет рекомендацию для пробежки, логика должна быть следующей:

  1. Если идёт дождь (is_raining == True), возвращается «На улице дождь».
  2. Если температура меньше 5 градусов, возвращается «Слишком холодно».
  3. Если температура находится в диапазоне от 5 до 15 градусов, возвращается «На пробежку!».
  4. Если температура превышает 15 градусов, возвращается «Слишком жарко».

Рассмотрим возможные варианты:

  • Варианты с while некорректны, так как while используется для циклов, а здесь необходимо условие.
  • Вариант 5 некорректен, так как переменные raining_status и temperature_status не определены в коде.
  • Вариант 3 некорректен, так как синтаксис elif temperature >= 5 and <= 15 вызывает ошибку.

📌Правильный ответ:

  1. if is_raining: в первом случае и elif temperature >= 5 and temperature <= 15: во втором

Вопрос 4:

Вы разрабатываете скрипт для управления контрольно-кассовой техникой в магазине. Каждое устройство имеет числовой номер. Код должен проверять подключение устройств. Какие устройства и в каком порядке будут проверены?

Код:

for device_id in range(1, 4):
if device_id == 2:
continue
print("Проверка устройства", device_id)
print("Проверка завершена")

Варианты ответа:

  1. 1 и 3
  2. 1, 3 и 2
  3. 1, 3 и 4
  4. 1, 2 и 3
  5. Только 2

Обоснование:

  1. Цикл for проходит через значения, возвращаемые функцией range(1, 4). Она генерирует числа от 1 до 3 включительно.
  2. Условие if device_id == 2: проверяет, является ли текущее значение device_id равным 2. Если это так, выполняется команда continue, которая пропускает текущую итерацию цикла.
  3. Следовательно, для значения device_id == 2 код внутри цикла (вывод строки) не выполняется.
  4. Остальные значения (1 и 3) проходят проверку, и для них выводится строка Проверка устройства.

Итак, будут проверены устройства 1 и 3.

📌Правильный ответ: 1. 1 и 3

Вопрос 5:

Какой из следующих фрагментов кода является примером вызова функции calculate_payment с передачей аргументов?

Варианты ответа:

  1. def calculate_payment(): pass
  2. print(calculate_payment())
  3. pay = calculate_payment(1000, 0.05, 12)
  4. for i in range(10): calculate_payment()
  5. def calculate_payment(x = 1000, y, z)

Обоснование:

  • Вариант 1: def calculate_payment(): pass — это определение функции без реализации, а не вызов.
  • Вариант 2: print(calculate_payment()) — это вызов функции без передачи аргументов. Нет аргументов в скобках, поэтому он не подходит.
  • Вариант 3: pay = calculate_payment(1000, 0.05, 12) — это корректный вызов функции с передачей трёх аргументов: 1000, 0.05 и 12.
  • Вариант 4: for i in range(10): calculate_payment() — это вызов функции внутри цикла, но аргументы также не передаются.
  • Вариант 5: def calculate_payment(x = 1000, y, z) — это некорректное определение функции, так как параметр с дефолтным значением (x = 1000) идёт перед обязательными параметрами y и z, что вызовет ошибку синтаксиса.

📌Правильный ответ: 3. pay = calculate_payment(1000, 0.05, 12)

Вопрос 6:

Что возвращает этот код?

Код:

def modify(lst):
lst.append(4)
return lst
my_list = [1, 2, 3]
new_list = modify(my_list)
print(new_list, my_list)

Варианты ответа:

  1. [1, 2, 3, 4] [1, 2, 3]
  2. [1, 2, 3, 4] [1, 2, 3, 4]
  3. AttributeError
  4. [4] [4]
  5. [4] [1, 2, 3]

Обоснование:

  1. В Python списки передаются в функции по ссылке, что означает, что изменения, внесённые в список внутри функции, будут видны снаружи.
  2. Функция modify(lst) добавляет элемент 4 в конец переданного списка с помощью метода append().
  3. После вызова функции modify(my_list), список my_list изменяется и становится [1, 2, 3, 4]. Так как функция возвращает изменённый список, переменная new_list также содержит [1, 2, 3, 4].
  4. Таким образом, при выполнении print(new_list, my_list) будет выведено дважды один и тот же изменённый список [1, 2, 3, 4].

📌Правильный ответ: 2. [1, 2, 3, 4] [1, 2, 3, 4]

Вопрос 7:

Какое утверждение об отличиях между методами .append() и .extend() НЕВЕРНО?

Варианты ответа:

  1. .extend() изменяет исходный список, добавляя к нему элементы из итерируемого объекта, тогда как .append() добавляет элемент в виде отдельного элемента.
  2. .append() добавляет элемент в конец списка, а .extend() добавляет все элементы из другого списка.
  3. .extend() возвращает новый список, а .append() изменяет исходный список и возвращает None.
  4. .append() принимает только один аргумент, тогда как .extend() принимает любой итерируемый объект.
  5. .append() добавляет один элемент в конец списка, тогда как .extend() добавляет элементы из другого итерируемого объекта.

Обоснование:

1. Метод .append() добавляет один элемент (любой объект) в конец списка.
Пример:

lst = [1, 2]
lst.append([3, 4]) # Результат: [1, 2, [3, 4]]

2. Метод .extend() добавляет элементы из переданного итерируемого объекта в список.
Пример:

lst = [1, 2]
lst.extend([3, 4]) # Результат: [1, 2, 3, 4]

3. Оба метода изменяют исходный список. Они не возвращают новый список, а возвращают None.
4. .append() принимает только один аргумент (любой тип данных), а .extend() принимает итерируемый объект, элементы которого добавляются в список.

Следовательно, утверждение ".extend() возвращает новый список, а .append() изменяет исходный список и возвращает None" является неверным.

📌Правильный ответ: 3. .extend() возвращает новый список, а .append() изменяет исходный список и возвращает None.

Вопрос 8:

Вы создали объект my_laptop класса Laptop, который описан ниже. Что произойдет, если вызвать my_laptop.toggle_power()?

Код:

import time
class Laptop:
def __init__(self):
self.power_on = False
self.battery_level = 30
def toggle_power(self):
if self.battery_level > 20:
self.power_on = not self.power_on
else:
time.sleep(3)
self.power_on = False

Варианты ответа:

  1. Ноутбук включится через 3 минуты.
  2. Ноутбук включится сразу.
  3. Ноутбук включится, а затем выключится через 3 минуты.
  4. Ноутбук выключится через 3 минуты.
  5. Ноутбук останется выключенным.

Обоснование:

1. При создании объекта my_laptop:

  • power_on устанавливается в False.
  • battery_level устанавливается в 30.

2. При вызове my_laptop.toggle_power():

  • Метод проверяет, превышает ли уровень заряда батареи 20.
  • В данном случае battery_level = 30, что больше 20. Условие if self.battery_level > 20: выполняется.
  • Тогда состояние power_on переключается с False на True (логическая операция not self.power_on).
  • Блок else (который вызывает задержку через time.sleep(3)) не выполняется, так как условие if истинно.

3. Результатом вызова my_laptop.toggle_power() будет немедленное включение ноутбука.

📌Правильный ответ: 2. Ноутбук включится сразу.

Вопрос 9:

Какой код создаёт список вида [0, 2, 4, 6, 8]?

Варианты ответа:

  1. [x for x in range(10) if x % 2 == 0]
  2. {x**2 for x in range(5)}
  3. [x/y for x in range(5) for y in range(1, x)]
  4. [x * 2 for x in range(5) if x < 3]
  5. (x + 1 for x in range(5))

Обоснование:

  • Вариант 1: [x for x in range(10) if x % 2 == 0] — это генератор списка, который выбирает только числа из range(10), делящиеся на 2 (чётные числа). Результатом будет список [0, 2, 4, 6, 8]. Этот вариант является правильным.
  • Вариант 2: {x**2 for x in range(5)} создаёт множество (не список) квадратов чисел от 0 до 4: {0, 1, 4, 9, 16}. Это не соответствует требуемому виду.
  • Вариант 3: [x/y for x in range(5) for y in range(1, x)] создаёт список с использованием двух циклов, где выполняется деление x / y. Этот код не создаст список [0, 2, 4, 6, 8] и вызовет ошибку деления на 0 при x = 0.
  • Вариант 4: [x * 2 for x in range(5) if x < 3] создаёт список, умножая числа из range(5) на 2, но только если они меньше 3. Результатом будет [0, 2, 4], а не [0, 2, 4, 6, 8].
  • Вариант 5: (x + 1 for x in range(5)) — это генератор (не список), который создаёт последовательность [1, 2, 3, 4, 5]. Это не соответствует задаче.

📌Правильный ответ: 1. [x for x in range(10) if x % 2 == 0]

Вопрос 10:

Код ниже предназначен для записи списка чисел в файл numbers.txt, каждое число должно быть на новой строке. Какой из вариантов корректно описывает поведение кода?

Код:

numbers = [1, 2, 3, 4, 5]
with open('numbers.txt', 'w') as file:
for number in numbers:
file.write(str(number))

Варианты ответа:

  1. Код не выполнит задачу, так как записывает все числа без разделителей в одну строку.
  2. Код вызовет ошибку, так как файл открыт в неправильном режиме.
  3. Код работает корректно и записывает каждое число на новой строке.
  4. Код вызовет ошибку выполнения, так как число не может быть напрямую записано в файл.
  5. Код неэффективен, но выполнит задачу без ошибок.

Обоснование:

  1. Код открывает файл numbers.txt в режиме записи ('w'), что корректно для записи в файл.
  2. Внутри цикла для каждого числа из списка:Метод file.write() преобразует число в строку с помощью str(number) и записывает её в файл.
    Однако после каждого числа не добавляется символ новой строки (\n), поэтому все числа будут записаны в одну строку без разделителей.
  3. В результате файл будет содержать строку: 12345.

Для записи чисел на новой строке нужно было использовать:

file.write(str(number) + '\n')

Таким образом, код не выполнит задачу, так как записывает все числа без разделителей в одну строку.

📌Правильный ответ: 1. Код не выполнит задачу, так как записывает все числа без разделителей в одну строку

Вопрос 11:

Какую информацию можно получить с помощью модуля os в Python?

Варианты ответа:

  1. Наличие установленных сторонних модулей
  2. Информацию о версии Python
  3. Список файлов в текущем каталоге
  4. Размер объекта в памяти
  5. Версию операционной системы

Обоснование: Модуль os в Python предоставляет интерфейс для взаимодействия с операционной системой. Он позволяет выполнять такие задачи, как:

  • Получение информации о системе (например, версии ОС с помощью os.uname() или os.name).
  • Работа с файловой системой (например, получение списка файлов в каталоге с помощью os.listdir()).
  • Управление процессами, окружением и каталогами.

Рассмотрим варианты:

1. Наличие установленных сторонних модулей: Для этого используется модуль pkg_resources или pip, а не os.

2. Информация о версии Python: Для этого используется модуль sys (например, sys.version), а не os.

3. Список файлов в текущем каталоге: Это возможно с помощью метода os.listdir(). Например:

import os
print(os.listdir('.'))

Этот вариант корректен.

4. Размер объекта в памяти: Для этого используется модуль sys и функция sys.getsizeof(), а не os.

5. Версия операционной системы: Это возможно с помощью метода os.uname() (на Unix-подобных системах) или os.name.

📌Правильные ответы: 3. Список файлов в текущем каталоге

Вопрос 12:

Как создать временный файл, который НЕ удалится после закрытия автоматически?

Варианты ответа:

  1. tempfile.mktemp()
  2. tempfile.TemporaryFile(delete=False)
  3. tempfile.GetTempFileName()
  4. tempfile.NamedTemporaryFile(delete=False)
  5. tempfile.SpooledTemporaryFile(max_size=0)

Обоснование:

  1. tempfile.mktemp(): Создаёт временное имя файла, но сам файл не создаётся. Использование этого метода небезопасно, так как файл может быть перезаписан.
  2. tempfile.TemporaryFile(delete=False): Метод TemporaryFile создаёт временный файл, который по умолчанию удаляется после закрытия. Параметр delete=False предотвращает автоматическое удаление файла.
  3. tempfile.GetTempFileName(): Этот метод устарел и используется в других языках, таких как C++. В Python его не существует.
  4. tempfile.NamedTemporaryFile(delete=False): Создаёт временный файл с именем, который не удаляется автоматически, если указан параметр delete=False.
  5. tempfile.SpooledTemporaryFile(max_size=0): Создаёт временный файл, который сохраняется в памяти до достижения размера max_size. Этот файл автоматически удаляется после закрытия.

Вывод: Чтобы создать временный файл, который не удаляется автоматически, используется tempfile.NamedTemporaryFile(delete=False).

📌Правильный ответ: 4. tempfile.NamedTemporaryFile(delete=False)

Вопрос 13:

Следующее выражение используется для извлечения email-адресов из текста. Какой из перечисленных ниже адресов НЕ подойдет для этого регулярного выражения?

Регулярное выражение:

[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-z]{3,}

Варианты ответа:

  1. username@subdomain.domain.com
  2. mail@domain2.technology
  3. user.name@domain.com
  4. user_name@do-main.com
  5. username123@subdomain.mail.ru

Обоснование:

1. Регулярное выражение состоит из следующих частей:

  • [a-zA-Z0-9._%+-]+: Локальная часть email-адреса. Разрешает символы латиницы, цифры, точки (.), подчёркивания (_), процента (%), плюса (+) и дефиса (-).
  • @: Обязательный символ «собака».
  • [a-zA-Z0-9.-]+: Доменная часть перед точкой. Разрешает латинские буквы, цифры, точки (.) и дефисы (-).
  • \.[a-z]{3,}: Домен верхнего уровня, состоящий из не менее чем 3 латинских символов (например, .com, .org).

2. Рассмотрим каждый адрес:

  • username@subdomain.domain.com: Подходит. Все части соответствуют регулярному выражению.
  • mail@domain2.technology: Подходит. Домен верхнего уровня .technology содержит более 3 букв.
  • user.name@domain.com: Подходит. Локальная и доменная части соответствуют требованиям.
  • user_name@do-main.com: Подходит. Дефис в домене разрешён.
  • username123@subdomain.mail.ru: НЕ подходит. Домен верхнего уровня .ru содержит только 2 буквы, тогда как регулярное выражение требует минимум 3 символа.

📌Правильный ответ: 5. username123@subdomain.mail.ru

👉🏻Навигация и ссылки по всем материалам в Telegram

Заключение

Дорогие читатели! Если материалы данной статьи помогли вам успешно пройти тест, буду признателен, если вы поставите лайк 👍🏻 именно той статье, которая соответствовала вашему уровню подготовки. Также, если тестирование оказалось неудачным ❌, пожалуйста, оставьте комментарий 📝 с указанием количества ошибок допущенных в тесте.

Эта обратная связь чрезвычайно важна. Она позволит в дальнейшем проанализировать эффективность материалов, а также создать аналитическое заключение для всей серии статей по прохождению тестирования на платформе. Спасибо за вашу помощь в совершенствовании контента!