Промежуточный Python: Структуры данных, функции и ООП
Объясните разницу между списком (list) и кортежем (tuple) в Python.
Ответ:
Списки являются изменяемыми (mutable), что означает, что их элементы могут быть изменены после создания, и определяются с использованием квадратных скобок []. Кортежи являются неизменяемыми (immutable), что означает, что их элементы не могут быть изменены, и определяются с использованием круглых скобок (). Кортежи, как правило, работают быстрее и могут использоваться в качестве ключей словаря.
Что такое генератор словаря (dictionary comprehension)? Приведите пример.
Ответ:
Генератор словаря — это лаконичный способ создания словарей. Он состоит из выражения, за которым следует предложение for, а затем ноль или более предложений for или if. Например: squares = {x: x*x for x in range(5)} создает {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}.
Каково назначение *args и **kwargs в определениях функций?
Ответ:
*args позволяет функции принимать произвольное количество позиционных аргументов, которые собираются в кортеж. **kwargs позволяет функции принимать произвольное количество именованных аргументов, которые собираются в словарь. Они обеспечивают гибкие сигнатуры функций.
Объясните концепцию декоратора (decorator) в Python.
Ответ:
Декоратор — это шаблон проектирования, который позволяет изменять или расширять функциональность функции или метода без явного изменения их исходного кода. По сути, это функция, которая принимает другую функцию в качестве аргумента, добавляет некоторую функциональность и возвращает новую функцию. Они часто используются для логирования, измерения времени выполнения или контроля доступа.
В чем разница между методами __init__ и __new__ в классах Python?
Ответ:
__new__ — это статический метод, ответственный за создание и возврат нового экземпляра класса до вызова __init__. __init__ — это метод экземпляра, который инициализирует вновь созданный объект. __new__ редко переопределяется, если только вам не нужно контролировать сам процесс создания объекта, например, для синглтонов (singletons).
Опишите переопределение методов (method overriding) и перегрузку методов (method overloading) в Python.
Ответ:
Переопределение метода происходит, когда подкласс предоставляет конкретную реализацию для метода, который уже определен в его суперклассе. Python не поддерживает традиционную перегрузку методов (несколько методов с одинаковым именем, но разными параметрами) напрямую; вместо этого вы можете использовать аргументы по умолчанию или *args/**kwargs для достижения аналогичной гибкости.
Что такое генератор (generator) в Python и почему его следует использовать?
Ответ:
Генератор — это функция, которая возвращает итератор, производящий последовательность результатов по одному с использованием ключевого слова yield, вместо возврата одного значения. Они эффективны по памяти, поскольку не хранят всю последовательность в памяти, что делает их идеальными для больших наборов данных или бесконечных последовательностей.
Объясните Global Interpreter Lock (GIL) в Python.
Ответ:
GIL — это мьютекс (mutex), который защищает доступ к объектам Python, предотвращая одновременное выполнение байт-кода Python несколькими нативными потоками. Это означает, что даже на многоядерных процессорах только один поток может выполнять байт-код Python в любой момент времени. Он упрощает управление памятью, но может ограничивать истинное параллельное выполнение для задач, интенсивно использующих процессор (CPU-bound tasks).
Каково назначение super() в Python?
Ответ:
super() используется для вызова метода из родительского или соседнего класса. Он позволяет получить доступ к унаследованным методам, которые были переопределены в подклассе, обеспечивая правильный порядок разрешения методов (Method Resolution Order, MRO) в сложных иерархиях наследования. Он часто используется в методах __init__ подклассов.
Как обрабатывать исключения (exceptions) в Python? Приведите базовый пример.
Ответ:
Исключения обрабатываются с использованием блоков try, except, else и finally. Блок try содержит код, который может вызвать исключение. except перехватывает конкретные исключения. else выполняется, если исключение не произошло, а finally выполняется всегда, независимо от того, произошло исключение или нет. Пример: try: 1/0 except ZeroDivisionError: print('Cannot divide by zero').
В чем разница между поверхностным (shallow) и глубоким (deep) копированием?
Ответ:
Поверхностное копирование создает новый составной объект, а затем вставляет ссылки на объекты, найденные в оригинале. Если оригинал содержит изменяемые объекты, изменения в этих объектах будут отражены в поверхностной копии. Глубокое копирование создает новый составной объект, а затем рекурсивно вставляет копии объектов, найденных в оригинале, обеспечивая полную независимость.
Объясните концепцию менеджеров контекста (context managers) и оператора with.
Ответ:
Менеджеры контекста предоставляют чистый способ управления ресурсами, гарантируя, что операции настройки и очистки выполняются правильно, даже если возникают ошибки. Оператор with используется для автоматического управления получением и освобождением ресурсов. Распространенные случаи использования включают работу с файлами, соединения с базами данных и блокировки, обеспечивая правильное закрытие ресурсов.