Генераторы списков и встроенные функции: вопросы для собеседования (часть 2)

List comprehensions, dict comprehensions, map, filter, zip, enumerate — идиоматический Python, который ожидают от аналитика. На собеседовании просят переписать цикл в comprehension, использовать sorted с ключом или объяснить разницу между map и генератором списка. Владение этими конструкциями показывает зрелость как Python-разработчика.

Коллекции и структуры данныхЦиклы и условияИсключения и отладкаРабота с файлами: JSON и CSVФункции и аргументыИтераторы и генераторыNumPy: основыPandas и DataFrameСинтаксис и типы данных

Вопросы 610 из 20

6Нужно преобразовать `user_ids = [1, -1, 2]` в список строк только для положительных значений. Какой вариант обычно читается проще?
A`[str(x) for x in user_ids if x > 0]`
B`list(map(str, filter(lambda x: x > 0, user_ids)))`
C`list(map(lambda x: str(x), user_ids))`
D`list(filter(lambda x: str(x) > 0, user_ids))`
Ответ: Списочное включение с фильтром и преобразованием одним выражением читается короче связки `map()` + `filter()` + `lambda`.

Запись `[str(x) for x in user_ids if x > 0]` сразу описывает: «возьми каждый `x` из списка, оставь положительные и приведи к строке». Вариант с `map()` и `filter()` делает то же самое, но добавляет вложенные функции и `lambda`. `list(map(lambda x: str(x), user_ids))` преобразует все элементы, не отфильтровав отрицательные. В последнем варианте `str(x) > 0` — это сравнение строки с числом: в Python 3 такой код вообще выбросит `TypeError` при первом же вызове.

Подробный разбор →
7Дан список `vals = [0, 1, 2]`. Что вернёт выражение `[x if x % 2 == 0 else -1 for x in vals]`?
A`[0, 1, 2]`
B`[-1, -1, -1]`
C`[0, -1, 2]`
D`[-1, 1, -1]`
Ответ: Тернарное выражение `x if cond else y` подставляет одно из двух значений на каждом шаге списочного включения.

В выражении `[x if x % 2 == 0 else -1 for x in vals]` для каждого `x` проверяется условие: если чётное — оставляем `x`, иначе подставляем `-1`. Для `vals = [0, 1, 2]` получится `[0, -1, 2]`. Это не фильтр: длина результата всегда равна длине исходного списка. Вариант `[-1, 1, -1]` соответствовал бы инвертированному условию (заменять чётные, оставлять нечётные), а `[-1, -1, -1]` — постоянной замене без проверки.

Подробный разбор →
8У вас есть список словарей `users` с ключами `id` и `is_active`. Нужно получить список идентификаторов только активных пользователей. Какое решение обычно проще читать, чем комбинация `map` и `filter` с анонимными функциями?
A`map(lambda u: u["id"], filter(lambda u: u["is_active"], users))`
B`[u["id"] for u in users if u.get("is_active")]`
C`{u["id"]: u for u in users if u.get("is_active")}`
D`[u for u in users if u.get("is_active") == True]`
Ответ: Списочное включение `[u["id"] for u in users if u.get("is_active")]` напрямую возвращает список идентификаторов активных пользователей.

Целевой результат — это список значений `id`, поэтому подходит обычное списочное включение с фильтром по `is_active`. Связка `map()` + `filter()` даёт похожий результат, но возвращает ленивый итератор и читается тяжелее из-за двух `lambda`. Конструкция с двоеточием в фигурных скобках — это словарь по `id`, а не список. Вариант `[u for u in users if ...]` собирает целиком сами словари пользователей, а не их идентификаторы.

Подробный разбор →
9Нужно проверить, что все значения в списке `prices` строго положительные. Какое выражение вернёт `True` только если каждый элемент больше нуля?
A`any(p > 0 for p in prices)`
B`[p > 0 for p in prices]`
C`sum(p > 0 for p in prices)`
D`all(p > 0 for p in prices)`
Ответ: `all(...)` возвращает `True` только когда каждый элемент удовлетворяет условию.

`all(p > 0 for p in prices)` обходит все цены и возвращает `True`, лишь когда условие истинно для каждой. `any` вернёт `True` уже при первом положительном элементе — это «хотя бы один», а не «все». Списочное включение `[p > 0 for p in prices]` отдаёт список булевых значений, а не один общий флаг. `sum(p > 0 for p in prices)` посчитает количество положительных элементов, что не отвечает на вопрос «строго все».

Подробный разбор →
10Есть список строк `raw = ["10", "", "3"]`. Нужно получить список целых чисел только из непустых строк. Какой вариант корректен и читаем?
A`[int(x) for x in raw]`
B`list(filter(None, map(int, raw)))`
C`list(filter(int, raw))`
D`[int(x) for x in raw if x]`
Ответ: Сначала отбрасываем пустые строки фильтром `if x`, затем превращаем оставшиеся в числа через `int(x)`.

`[int(x) for x in raw if x]` сначала отсеивает пустые строки (для них `bool("") = False`), и только потом вызывает `int(x)` — поэтому исключения не будет. `[int(x) for x in raw]` без фильтра пытается преобразовать пустую строку и падает с `ValueError`. Вариант с `filter(None, map(int, raw))` тоже сначала вызывает `int()` для всех элементов и падает на пустой строке. `list(filter(int, raw))` использует `int` как предикат к строкам и не приводит их к числу, а также падает с ошибкой при пустой строке.

Подробный разбор →
1234

Хотите тренировать интерактивно?

В приложении — таймер, прогресс, стрики и 1700+ вопросов по всем темам.

Тренировать Python в Telegram

Другие темы: Python

Коллекции и структуры данныхЦиклы и условияИсключения и отладкаРабота с файлами: JSON и CSVФункции и аргументыИтераторы и генераторыNumPy: основыPandas и DataFrameСинтаксис и типы данных