Коллекции и структуры данных: вопросы для собеседования (часть 5)
Списки, словари, множества, кортежи — базовые структуры данных Python, без которых не обойтись ни в анализе, ни на собеседовании. Спрашивают про сложность операций, разницу между list и tuple, когда использовать set вместо list. Понимание коллекций показывает, что кандидат пишет эффективный код, а не просто «работающий».
Вопросы 21–25 из 40
21Есть список чисел `values = [100, 50, 50]` (список не пустой). Как корректно посчитать среднее значение средствами стандартного Python без библиотек?
A`sum(values) / len(values)`: сумма всех элементов делится на их количество
B`len(values) / sum(values)`: количество элементов делится на сумму всех значений
C`values.sum() / values.len()`: вызов методов списка для суммы и числа элементов
D`avg(values)`: вызов встроенной функции среднего значения по списку
Ответ: Среднее значение считается как `sum(values) / len(values)`.
`sum(values)` складывает элементы, а `len(values)` возвращает количество элементов в списке. Для среднего нужно разделить сумму на количество, поэтому `sum(values) / len(values)` — правильный ответ. У списка нет методов `.sum()` и `.len()`, а встроенной функции `avg()` в Python тоже не существует. Если список может быть пустым, добавляют проверку `len(values) > 0` перед делением, иначе будет `ZeroDivisionError`.
Подробный разбор → 22Есть `list` из 100 000 заблокированных идентификаторов пользователя в переменной `banned`. Для каждого из миллиона событий нужно проверить, заблокирован ли пользователь. Как ускорить проверку?
AПреобразовать `banned` в `tuple`: проверка через `in` у кортежа выполняется быстрее, чем у списка
BПреобразовать `banned` в `set`: проверка через `in` в среднем за `O(1)` через хеш-таблицу
CОставить `list` и применять модуль `bisect`: бинарный поиск даёт ускорение по сравнению с перебором
DОтсортировать `list` функцией `sorted`: оператор `in` после сортировки переключится на бинарный поиск
Ответ: Проверка принадлежности у `set` работает за O(1) в среднем, а у `list` — за O(n). Для массовых проверок `set` значительно быстрее.
`list` проверяет принадлежность последовательным перебором элементов — O(n). `set` использует хеш-таблицу, поэтому проверка принадлежности занимает O(1) в среднем. При 100 000 элементах и миллионе проверок разница огромна. Сортировка `list` не помогает: оператор `in` у `list` не использует бинарный поиск, а всегда делает линейный перебор. У `tuple` логика та же, что и у `list`.
Подробный разбор → 23Есть список словарей:
```python
users = [
{'name': 'Анна', 'age': 30},
{'name': 'Борис', 'age': 25}
]
```
Как отсортировать его по возрасту?
A`sorted(users, key='age')`: передать имя ключа строкой
B`users.sort(key='age', reverse=False)`: имя ключа строкой
C`users.sort_by('age', ascending=True)`: метод списка словарей
D`sorted(users, key=lambda u: u['age'])`: функция извлечения ключа
Ответ: Параметр `key` в `sorted()` принимает функцию, которая извлекает значение для сортировки из каждого элемента.
Вызов `sorted(users, key=lambda u: u['age'])` создаст новый список, отсортированный по значению ключа `'age'`. Функция `lambda u: u['age']` вызывается для каждого элемента и возвращает число, по которому идёт сортировка. Передать строку `'age'` напрямую нельзя — `key` ожидает вызываемый объект. Альтернатива лямбде — `operator.itemgetter('age')` из стандартной библиотеки.
Подробный разбор → 24Есть множество `s = {"a", "b"}`. Нужно удалить элемент `"c"`, если он есть, и не получать ошибку, если его нет. Какой способ корректен?
A`s.remove("c")`: удаляет элемент по значению или выбрасывает исключение при его отсутствии
B`s.discard("c")`: удаляет элемент по значению или ничего не делает при его отсутствии
C`del s["c"]`: удаление по ключу как у словаря, синтаксис применим к `dict` и `list`
D`s.pop("c")`: метод `.pop()` у множества аргументов не принимает и удаляет случайный элемент
Ответ: У множества `.discard()` удаляет элемент без ошибки, даже если элемента нет.
Метод `.remove("c")` выбросит исключение, если элемента нет в множестве. `.discard("c")` безопасен: удалит элемент при наличии и ничего не сделает при отсутствии. У множества нет индексации по ключу, поэтому `del s["c"]` не работает (это синтаксис для словаря или списка). `.pop()` у множества не принимает аргумент и удаляет произвольный элемент — попытка `s.pop("c")` приведёт к ошибке.
Подробный разбор → 25Есть список названий кампаний `campaigns` с повторами. Нужно получить список уникальных кампаний в отсортированном виде. Какой вариант корректен?
A`sorted(set(campaigns))`: дедупликация через `set`, затем сортировка с возвратом `list`
B`set(campaigns)`: убирает повторы, но возвращает `set` без гарантии порядка обхода
C`sorted(campaigns)`: сортирует значения, но повторы остаются в результирующем списке
D`set(sorted(campaigns))`: сортирует, но затем оборачивает результат в неупорядоченный `set`
Ответ: Сначала `set()` для уникальности, затем `sorted()` для получения отсортированного списка.
`set(campaigns)` снимает повторы, но возвращает множество без гарантированного порядка. `sorted(campaigns)` сортирует, но дубликаты остаются. Комбинация `sorted(set(campaigns))` сначала убирает повторы, затем возвращает новый отсортированный `list`. Обратный порядок — `set(sorted(...))` — теряет сортировку, потому что `set` не сохраняет порядок.
Подробный разбор →