List comprehensions, dict comprehensions, map, filter, zip, enumerate — идиоматический Python, который ожидают от аналитика. На собеседовании просят переписать цикл в comprehension, использовать sorted с ключом или объяснить разницу между map и генератором списка. Владение этими конструкциями показывает зрелость как Python-разработчика.
Конструкция `{u['city'].lower() for u in users if u.get('city')}` использует множество (фигурные скобки без двоеточия), приводит каждый город к нижнему регистру и заранее отбрасывает записи с отсутствующим или пустым `city`. Вариант с квадратными скобками — это список, в нём останутся дубликаты. Вариант `set(u['city'].lower() for u in users)` упадёт на отсутствующих ключах, потому что фильтра нет. Последний вариант сохраняет регистр, поэтому одинаковые города в разном регистре будут считаться разными.
Подробный разбор →В выражении `{v: k for k, v in code_to_name.items()}` мы явно меняем местами ключ и значение: новый ключ — это старое значение `v`, а новое значение — старый ключ `k`. Важно, чтобы значения были уникальны, иначе при инвертировании ключи начнут перезаписываться.
Подробный разбор →Выражение `{e.split("@")[1] for e in emails}` берёт часть после `@` для каждого email. Результат — `set`, поэтому повторяющиеся домены (например, `"x.com"`) автоматически схлопываются в один элемент.
Подробный разбор →`[u["email"].lower() for u in users if u.get("email")]` сразу выражает намерение и возвращает список, как требуется. Вариант с `map()` и `filter()` делает то же самое, но требует двух `lambda` и читается тяжелее. Вариант с `u.get("email", "")` пропускает только `None`, но если поле есть и равно пустой строке, фильтр `is not None` оставит её и `.lower()` от `""` даст `""` в итоговом списке. Третий вариант с фигурными скобками без двоеточия даёт `set`, а не список, и порядок теряется.
Подробный разбор →Конструкция `[x for batch in batches for x in batch]` сначала перебирает каждый `batch`, затем элементы `x` внутри него. Пустой `[]` просто не добавляет элементов в результат, поэтому итог — плоский `[101, 102, 103]`. Порядок `for`-ов важен: внешний цикл должен идти первым, иначе переменная внутреннего цикла не успеет быть определена и интерпретатор выдаст `NameError`. Пустые подсписки никак не нарушают результат, они просто не вкладывают ничего на свой шаг.
Подробный разбор →В приложении — таймер, прогресс, стрики и 1700+ вопросов по всем темам.
Тренировать Python в Telegram