Ответы на вопросы по Python
1. Что такое генераторы в Python и чем они отличаются от списков?
Генераторы — это функции, которые возвращают итератор и позволяют лениво (по требованию) генерировать значения с помощью ключевого слова yield. В отличие от списков, они не хранят все элементы в памяти, а вычисляют их по мере необходимости.
Отличия от списков:
- Память: Генераторы экономят память, так как элементы генерируются «на лету».
- Скорость: Генераторы быстрее для больших данных.
- Однопроходность: Генераторы обычно используются один раз (после итерации элементы «заканчиваются»).
- Доступ: В списках возможен произвольный доступ по индексу, в генераторах — только последовательный.
Пример:
# Генератор
def square_numbers(n):
for i in range(n):
yield i ** 2
gen = square_numbers(5)
print(list(gen)) # [0, 1, 4, 9, 16]
# Список
squares_list = [i ** 2 for i in range(5)] # [0, 1, 4, 9, 16]
2. Объясните разницу между списком, кортежем и множеством в Python.
- Список (list): Упорядоченная, изменяемая коллекция. Допускает дубликаты.
lst = [1, 2, 3, 3] lst.append(4) # [1, 2, 3, 3, 4]
- Кортеж (tuple): Упорядоченная, неизменяемая коллекция. Допускает дубликаты. Быстрее списков.
tup = (1, 2, 3, 3) # tup[0] = 5 # Ошибка: нельзя изменить
- Множество (set): Неупорядоченная коллекция уникальных элементов. Изменяемое (кроме frozenset). Поддерживает операции объединения, пересечения и т.д.
s = {1, 2, 3, 3} # {1, 2, 3} s.add(4) # {1, 2, 3, 4}
3. Что такое декораторы в Python и приведите пример их использования.
Декораторы — это функции, которые изменяют поведение других функций или методов, не изменяя их код. Они принимают функцию как аргумент и возвращают новую функцию.
Пример: Декоратор для измерения времени выполнения.
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
print(f"Время выполнения: {time.time() - start:.2f} сек")
return result
return wrapper
@timer
def slow_function():
time.sleep(2)
slow_function() # Вывод: Время выполнения: 2.00 сек
4. Объясните, как работает механизм наследования в Python и что такое множественное наследование.
Наследование позволяет классу (дочернему) наследовать атрибуты и методы другого класса (родительского).
Множественное наследование — когда класс наследуется от нескольких родительских классов. Порядок наследования определяется MRO (Method Resolution Order).
Пример:
class A:
def greet(self):
print("Привет от A")
class B:
def greet(self):
print("Привет от B")
class C(A, B):
pass
obj = C()
obj.greet() # Привет от A (сработает метод из A, так как он первый в MRO)
print(C.__mro__) # Порядок разрешения методов: C -> A -> B -> object
5. Что такое контекстные менеджеры в Python и как создать свой собственный?
Контекстные менеджеры позволяют управлять ресурсами (например, файлами) с помощью конструкции with. Они автоматически вызывают методы __enter__() (при входе) и __exit__() (при выходе).
Создание своего контекстного менеджера:
- Через класс:
class MyContextManager: def __enter__(self): print("Вход в контекст") return self def __exit__(self, exc_type, exc_val, exc_tb): print("Выход из контекста") with MyContextManager() as cm: print("Внутри контекста") - Через contextlib:
from contextlib import contextmanager @contextmanager def my_context(): print("Вход") yield print("Выход") with my_context(): print("Внутри")
6. Объясните разницу между модулем и пакетом в Python.
- Модуль: Файл с расширением .py, содержащий код (функции, классы, переменные).
# module.py def hello(): print("Hello") - Пакет: Каталог, содержащий модули и файл __init__.py (может быть пустым). Позволяет организовывать модули в пространства имён.
mypackage/ __init__.py module1.py module2.py
7. Что такое GIL в Python и как он влияет на многопоточность?
GIL (Global Interpreter Lock) — глобальная блокировка интерпретатора, которая позволяет выполняться только одному потоку Python за раз (даже на многопроцессорных системах).
Влияние:
- Многопоточность в Python неэффективна для CPU-задач (например, вычислений), так как потоки выполняются последовательно.
- GIL не мешает I/O-задачам (сеть, файлы), так как во время ожидания освобождается.
Решение для CPU-задач: Использовать многопроцессорность (multiprocessing) или асинхронность.
8. Как работает сборщик мусора в Python и что такое циклические ссылки?
Сборщик мусора автоматически удаляет объекты, которые больше не используются. Основной механизм — подсчёт ссылок. Когда счётчик ссылок объекта становится нулевым, память освобождается.
Циклические ссылки возникают, когда объекты ссылаются друг на друга, образуя цикл. Пример:
class Node:
def __init__(self):
self.ref = None
a = Node()
b = Node()
a.ref = b
b.ref = a # Циклическая ссылка
В этом случае счётчик ссылок никогда не станет нулевым. Для решения используется циклический сборщик мусора (GC), который обнаруживает и удаляет такие циклы.
9. Объясните разницу между методами экземпляра, класса и статическими методами в Python.
- Метод экземпляра: Принимает self (экземпляр класса). Работает с данными экземпляра.
class MyClass: def instance_method(self): return f"Вызван из {self}" - Метод класса: Принимает cls (класс). Определяется декоратором @classmethod. Используется для создания альтернативных конструкторов.
class MyClass: @classmethod def class_method(cls): return f"Вызван из {cls}" - Статический метод: Не принимает ни self, ни cls. Определяется декоратором @staticmethod. Это обычная функция внутри класса.
class MyClass: @staticmethod def static_method(): return "Простая функция"
10. Что такое асинхронное программирование в Python и как работают async и await?
Асинхронное программирование позволяет выполнять I/O-задачи (сеть, файлы) без блокировки потока. Использует однопоточную модель с кооперативной многозадачностью.
Ключевые понятия:
- async: Определяет асинхронную функцию (корутину).
- await: Приостанавливает выполнение корутины до завершения другой асинхронной операции.
Пример:
import asyncio
async def fetch_data():
await asyncio.sleep(2) # Имитация I/O-операции
return "Данные"
async def main():
result = await fetch_data()
print(result) # "Данные"
asyncio.run(main())
Асинхронный код выполняется в цикле событий (event loop), который переключается между корутинами при встрече await.