Python: Продвинутый уровень. Теоретическое задание.
В этой статье мы разберем тестовые задания продвинутого уровня по Python, состоящего из:
- Теоретической части – основные вопросы, которые могут встретиться, и как правильно на них отвечать.
- Практической части – решение практического задания с детальным разбором, рассмотрено в статье Python: Продвинутый уровень. Практическое задание
Вопрос №1
Какой из встроенных типов данных Python лучше всего подходит для хранения списка IP-адресов?
Обоснование:
Для хранения списка IP-адресов оптимальным выбором будет список (list) или множество (set), в зависимости от требований задачи:
- Список: Подходит, если возможны дублирующиеся IP-адреса, либо если требуется сохранить порядок элементов.
- Множество: Подходит, если важна уникальность IP-адресов, поскольку множества автоматически устраняют дубли.
- Словарь: Используется для хранения пар ключ-значение и не подходит для простого хранения списка.
- Кортеж: Подходит, если данные неизменяемы, но не обладает преимуществами списков или множеств в данном контексте.
- Строки: Не подходят для хранения коллекций данных, так как это тип для текста.
Вопрос №2
Укажите, каким будет вывод этой программы в случае, если на вход подаются две строки — сначала «Python», потом «exit».
- Вводится "Python". Условие if c == 'exit': не выполняется.
- Переменная name обновляется: name = '' + 'Python' → name = 'Python'.
3. После завершения цикла выполняется вывод: print('I’m', name), где name содержит "Python".
📌Правильный ответ:
2. I’mPython
Пояснение:
Ответ слипается без пробела между "I’m" и "Python", так как в функции print() не добавлен пробел между строками.
Вопрос №3
Какой результат выведет этот код
Обоснование:
В данном коде используется изменяемый тип данных (список) в качестве значения по умолчанию для аргумента a. Это приводит к следующему поведению:
- При первом вызове функции add(), список a создается, в него добавляется 'A', и возвращается список ['A'].
- При втором вызове функции add(), используется тот же список, что и в первом вызове, поскольку значение по умолчанию для аргумента a сохраняется в памяти. В этот список снова добавляется 'A', и он становится ['A', 'A'].
Такое поведение связано с тем, что значения по умолчанию для аргументов функции в Python вычисляются один раз при определении функции и хранятся в памяти.
📌Правильный ответ:
4. ['A'] и ['A', 'A']
Вопрос №4
Вы работаете с большим набором данных и вам необходимо определить, какая из перечисленных встроенных функций Python наиболее эффективна для определения длины списка с использованием меньшего объема оперативной памяти.
- len(): Это встроенная функция Python, оптимизированная для определения длины коллекций (списки, строки и т.д.). Она выполняется быстро и не требует дополнительной памяти, поскольку доступ к длине коллекции осуществляется напрямую (у списка длина хранится как атрибут объекта).
- measure(), length(), size(): Такие функции не существуют в стандартной библиотеке Python, вызов их приведёт к ошибке NameError.
- count(): Эта функция используется для подсчёта количества вхождений определённого элемента в коллекции. Она не подходит для определения длины списка.
Пояснение:
Функция len() наиболее эффективна для определения длины списка, так как она оптимизирована для этой задачи и использует минимальный объём оперативной памяти.
Вопрос №5
Какой результат выведет этот код?
- Equals и Equals
- TypeError: A.meth() missing 1 required positional argument
- Not Equals и Equals
- Equals и Not Equals
- Not Equals и Not Equals
Первая строка вывода (a.counter == A.counter)
- a.counter — это экземплярное свойство, которому присвоено значение 100.
- A.counter — это атрибут класса, который остался равным 0.
- Сравнение a.counter == A.counter возвращает False, так как 100 != 0.
- Выводится 'Not Equals'.
Вторая строка вывода (a.meth() == A.meth(a))
- a.meth() вызывает метод экземпляра, который возвращает строку 'method'.
- A.meth(a) вызывает тот же метод, передавая явно экземпляр a в качестве аргумента self. Это эквивалентно вызову a.meth().
- Оба вызова возвращают 'method', так что сравнение a.meth() == A.meth(a) возвращает True.
- Выводится 'Equals'.
📌Правильный ответ:
3. Not Equals и Equals
Вопрос №6
Какой из вариантов позволяет создать список, содержащий элементы из двух списков, умноженные попарно, если они являются числами?
- [x * y if isinstance(x, (int, float)) and isinstance(y, (int, float)) else None for x, y in zip(list1, list2)]
- [x * y for x, y in zip(list1, list2) if type(x) is int and type(y) is int]
- [x * y for x, y in zip(list1, list2) if isinstance(x, int) and isinstance(y, int)]
- [x * y for x, y in zip(list1, list2) if isinstance(x, (int, float)) and isinstance(y, (int, float))]
- [x * y for x, y in zip(list1, list2) if type(x) == int and type(y) == int]
- 1-й вариант: Он проверяет типы с помощью isinstance() и учитывает числа (целые и с плавающей точкой). Однако, он добавляет None, если элемент не проходит проверку. Это не соответствует условию задачи, так как требуется оставить только произведения чисел.
- 2-й вариант: Используется type() для проверки на тип int. Это ограничивает проверку только целыми числами и игнорирует числа с плавающей точкой.
- 3-й вариант: Проверка с isinstance(x, int) также ограничивает только целые числа, исключая числа с плавающей точкой.
- 4-й вариант: Это правильный вариант, так как он проверяет, что элементы обоих списков являются числами (int или float), а затем вычисляет их произведение.
- 5-й вариант: Аналогично второму, использует строгую проверку на int через type() и игнорирует числа с плавающей точкой.
📌Правильный ответ:
4. [x * y for x, y in zip(list1, list2) if isinstance(x, (int, float)) and isinstance(y, (int, float))]
Пояснение:
Этот вариант наиболее универсален и корректно обрабатывает все числа (целые и с плавающей точкой).
Вопрос №7
Какая процедура или функция заранее НЕ определена в модуле os?
- Рекурсивное удаление директорий
- Редактирование прав на доступ к файлу
- Создание нового потока
- Создание символических ссылок (symlink)
- Создание дочернего процесса (форка)
- Рекурсивное удаление директорий:
В модуле os можно использовать функцию os.removedirs() для удаления директорий рекурсивно. - Редактирование прав на доступ к файлу:
Модуль os предоставляет функцию os.chmod() для изменения прав доступа к файлу. - Создание нового потока:
Модуль os не поддерживает создание потоков, так как он предназначен для работы с файловой системой и операционной системой. Для работы с потоками используется модуль threading. - Создание символических ссылок (symlink):
Модуль os предоставляет функцию os.symlink() для создания символических ссылок. - Создание дочернего процесса (форка):
В модуле os есть функция os.fork() (только на UNIX-подобных системах) для создания дочернего процесса.
📌Правильный ответ:
3. Создание нового потока
Пояснение:
Для создания потоков используется модуль threading, а не os. Модуль os не предоставляет функционала для работы с потоками.
Вопрос №8
В чем заключается главное различие между текстовым и бинарным режимами открытия файла в Python?
- Текстовый режим позволяет использовать методы строк при работе с содержимым файла, а бинарный — нет.
- В бинарном режиме Python автоматически преобразует переносы строк, в то время как в текстовом данные читаются и записываются как есть.
- В текстовом режиме файлы могут быть открыты только для чтения, в то время как в бинарном — для чтения и записи.
- В отличие от текстового, бинарный режим поддерживает кодировку символов, что важно для международной поддержки.
- Бинарный режим обеспечивает меньшую скорость чтения и записи данных из-за сложности обработки содержимого по сравнению с текстовым.
- 1: Неверно. Методы строк можно применять и к текстовому содержимому, считанному из файла в бинарном режиме, после преобразования байтов в строку (bytes.decode()).
- 2: Неверно. Наоборот, в текстовом режиме Python автоматически обрабатывает переносы строк, преобразуя их между форматами Windows (\r\n), Unix (\n) и Mac (\r). В бинарном режиме данные читаются и записываются "как есть", без изменений.
- 3: Неверно. Режимы чтения и записи определяются флагами 'r', 'w', 'rb', 'wb' и т.д., независимо от текстового или бинарного режима.
- 4: Неверно. Кодировка символов применяется только в текстовом режиме через параметр encoding. В бинарном режиме данные читаются и записываются в виде байтов без обработки кодировки.
- 5: Неверно. Скорость работы зависит от объема данных и их обработки, а не от текстового или бинарного режима.
📌Правильный ответ:
2. В бинарном режиме Python автоматически преобразует переносы строк, в то время как в текстовом данные читаются и записываются как есть.
Пояснение:
Текстовый режим автоматически обрабатывает переносы строк для платформенной совместимости, тогда как в бинарном режиме этого не происходит, данные остаются неизменными.
Вопрос №9
Выберите ответ, в котором указаны только те варианты, для которых следующее выражение вернет значение True.
re.match(r"^\+7-\(\d{3,5}\)-\d{3,5}?", text) is not None
Варианты номеров телефонов:
A. +7-(123)-45678
B. +7-123-45678
C. +7-12-345678
D. +7-(1234)-5678
E. +7-12345-678
- Регулярное выражение разбивается на части:^\+7- → строка должна начинаться с +7-.
\(\d{3,5}\) → в скобках должно быть от 3 до 5 цифр.
-\d{3,5}? → после тире должно быть от 3 до 5 цифр. - Анализ вариантов:
A: +7-(123)-45678
Соответствует выражению: код в скобках содержит 3 цифры, после тире — 5 цифр. Верно.
B: +7-123-45678
Не соответствует, так как нет скобок вокруг первых цифр. Не верно.
C: +7-12-345678
Не соответствует, так как в скобках должно быть от 3 до 5 цифр, а здесь только 2. Не верно.
D: +7-(1234)-5678
Соответствует выражению: код в скобках содержит 4 цифры, после тире — 4 цифры. Верно.
E: +7-12345-678
Не соответствует, так как отсутствуют скобки вокруг первых цифр. Не верно.
Пояснение:
Только варианты A и D соответствуют заданному регулярному выражению.
Вопрос №10: Выберите НЕВЕРНОЕ утверждение.
- Map используется для применения функции к каждому элементу исходной последовательности, а reduce — для агрегации элементов последовательности в одно значение.
- Reduce больше подходит для изменения размерности последовательности.
- И map, и reduce принимают в качестве аргумента лямбда-функцию.
- Reduce возвращает массив элементов, а map — одно значение.
- Map больше подходит для преобразования элементов списка.
- 1. Верно. map() применяет функцию ко всем элементам последовательности, возвращая новую последовательность, а reduce() сворачивает элементы последовательности в одно значение, применяя заданную функцию.
- 2. Неверно. reduce() не предназначен для изменения размерности последовательности. Он используется для агрегации, а не для трансформации последовательностей.
- 3. Верно. Оба — map() и reduce() — могут принимать лямбда-функции в качестве аргумента.
- 4. Неверно. Наоборот: reduce() возвращает одно значение (например, сумму или произведение элементов), а map() возвращает последовательность преобразованных элементов.
- 5. Верно. map() действительно лучше всего подходит для преобразования элементов последовательности, например, для изменения формата или типов данных.
📌Правильный ответ:
2. Reduce больше подходит для изменения размерности последовательности.
Пояснение:
reduce() используется для агрегации данных, а не для изменения размерности последовательностей.
Вопрос №11
Для чего целесообразно использовать вызов с помощью конструкции raise?
- Для выполнения кода, если условие истинно
- Для выполнения кода без обработки ошибок
- Для прерывания выполнения программы при возникновении ошибки
- Для определения функций
- Для итерации по элементам списка
- 1. Неверно. Конструкция raise предназначена для генерации исключений, а не для условного выполнения кода.
- 2. Неверно. raise используется именно для явного вызова исключений, а не для пропуска обработки ошибок.
- 3. Верно. Конструкция raise позволяет инициировать исключения, которые могут быть обработаны обработчиком (try-except) или привести к завершению программы, если обработчик отсутствует.
- 4. Неверно. Определение функций осуществляется с помощью ключевого слова def.
- 5. Неверно. Для итерации по элементам списка используются циклы, такие как for.
📌Правильный ответ:
3. Для прерывания выполнения программы при возникновении ошибки
Пояснение:
raise используется для генерации исключений в случаях, когда выполнение программы должно быть остановлено или перенаправлено в блок обработки ошибок.
Вопрос №12. Какой функции из модуля itertools соответствует по смыслу код ниже?
- compress: Эта функция выбирает элементы из одной последовательности на основе значений в другой (булевый список). Это не соответствует логике данного кода.
- count: Бесконечно генерирует числа, начиная с указанного значения. Не имеет отношения к фильтрации элементов.
- takewhile: Эта функция из itertools выполняет ту же логику, что и данный код. Она возвращает элементы из последовательности до тех пор, пока предикат возвращает True, и прекращает выполнение после первого False.
- cycle: Повторяет элементы последовательности бесконечно. Не имеет отношения к фильтрации.
- chain: Соединяет несколько итераторов в один. Это также не связано с фильтрацией.
📌Правильный ответ:
3. takewhile
Пояснение:
takewhile(predicate, iterable) возвращает элементы последовательности до тех пор, пока выполняется предикат, а затем прекращает итерацию, что полностью совпадает с логикой указанного кода.
Вопрос №13. Какой из вариантов содержит ОШИБКУ при использовании итератора?
- list(iter([4, 5, 6]))
- next(iter([1, 2, 3]))
- iter([1, 2, 3])[0]
- [x for x in iter([1, 2, 3])]
- sum(iter([1, 2, 3]))
- 1. list(iter([4, 5, 6])): Создает итератор из списка [4, 5, 6], а затем преобразует итератор обратно в список. Ошибки нет.
- 2. next(iter([1, 2, 3])): Создает итератор из списка [1, 2, 3] и возвращает первый элемент с помощью next(). Ошибки нет.
- 3. iter([1, 2, 3])[0]: Создает итератор из списка [1, 2, 3]. Однако итераторы в Python не поддерживают индексацию, поэтому возникает ошибка TypeError.
- 4. [x for x in iter([1, 2, 3])]: Создает список через генератор, проходя по итератору. Ошибки нет.
- 5. sum(iter([1, 2, 3])): Итератор используется для суммирования элементов. Ошибки нет.
📌Правильный ответ:
3. iter([1, 2, 3])[0]
Пояснение:
Итераторы не поддерживают индексацию. Попытка обращения к элементу через индекс ([0]) вызывает ошибку TypeError.
Вопрос №14: Что выводит этот код?
- Код вызывает функцию recursive_print с аргументом n=3.
- Первая итерация:n=3, так как n > 0, выполняется print(3).
Затем вызывается recursive_print(2). - Вторая итерация:n=2, так как n > 0, выполняется print(2).
Затем вызывается recursive_print(1). - Третья итерация:n=1, так как n > 0, выполняется print(1).
Затем вызывается recursive_print(0). - Четвертая итерация:n=0, так как n <= 0, выполняется print("Done").
Код завершает выполнение после вывода строки "Done".
3
2
1
Done
Пояснение:
Код использует рекурсию для последовательного вывода чисел от n до 1, а затем выводит "Done" при достижении n=0.
Вопрос №15
Какой из методов Python используется для эффективного управления использованием памяти при работе с большими наборами данных, обеспечивая как возможность итерации, так и снижение использования памяти?
- 1. dictionary comprehension: Создает словарь, используя аналогичную синтаксическую конструкцию, как в списочных выражениях. Однако словари полностью хранятся в памяти и не подходят для работы с большими данными.
- 2. regular function: Обычные функции не являются инструментом управления памятью. Они могут возвращать большие структуры данных, что приводит к значительным затратам памяти.
- 3. set comprehension: Аналогично list comprehension, создает множество, которое полностью загружается в память, что не подходит для экономии памяти при работе с большими наборами данных.
- 4. generator expression: Создает генератор, который вычисляет значения "лениво" (по мере необходимости), не загружая все данные в память. Это делает его идеальным инструментом для обработки больших наборов данных с минимальным использованием памяти.
- 5. list comprehension: Создает список, который полностью хранится в памяти. Это менее эффективно при работе с большими данными.
📌Правильный ответ:
4. generator expression
Пояснение:
Генераторные выражения позволяют обрабатывать элементы по одному, что снижает использование памяти по сравнению с другими структурами данных, такими как списки или словари.
Вопрос №16
Какое утверждение о декораторе lru_cache НЕВЕРНО?
- lru_cache можно использовать для мемоизации рекурсивных функций.
- По умолчанию lru_cache предназначен для кэширования результатов функции в пределах одного процесса Python.
- При использовании lru_cache первыми из кэша вытесняются элементы, неиспользованные дольше всех.
- lru_cache основан на алгоритме Least Recently Used.
- По умолчанию у lru_cache задано максимальное количество элементов в кэше, равное 256.
- 1. Верно. lru_cache идеально подходит для мемоизации рекурсивных функций, поскольку он запоминает результаты ранее выполненных вызовов, что ускоряет выполнение при повторных вызовах.
- 2. Верно. Кэш, созданный с помощью lru_cache, работает только в пределах одного процесса Python.
- 3. Верно. Алгоритм Least Recently Used (LRU) вытесняет из кэша самые старые элементы, которые дольше всего не использовались.
- 4. Верно. lru_cache действительно реализует алгоритм LRU для управления кэшем.
- 5. Неверно. По умолчанию у lru_cache максимальное количество элементов в кэше составляет 128, а не 256.
📌Правильный ответ:
5. По умолчанию у lru_cache задано максимальное количество элементов в кэше, равное 256.
Пояснение:
Значение по умолчанию для параметра maxsize в lru_cache — 128, но его можно изменить при вызове декоратора.
👉🏻Навигация и ссылки по всем материалам в Telegram
Заключение
Дорогие читатели! Если материалы данной статьи помогли вам успешно пройти тест на платформе, буду признателен, если вы поставите лайк 👍🏻 именно той статье, которая соответствовала вашему уровню подготовки. Также, если тестирование оказалось неудачным ❌, пожалуйста, оставьте комментарий 📝 с указанием количества ошибок допущенных в тесте.
Эта обратная связь чрезвычайно важна. Она позволит в дальнейшем проанализировать эффективность материалов, а также создать аналитическое заключение для всей серии статей по прохождению тестирования на платформе. Спасибо за вашу помощь в совершенствовании контента!