Почему выводится "Ann Bob" — разбор поведения min/max в Python
@python_quizРазберем этот квиз
Коротко о коде:

Вывод этой программы:

Ниже объясню, почему именно так, разберу варианты ответов и покажу безопасные альтернативы.
Что делает каждая строка
min(users, key=lambda u: len(u['logins']))
min выбирает элемент с минимальным значением ключа. Ключ — длина списка логинов. Для Ann длина 0, для Bob — 1, значит min возвращает запись Ann.
max(users, key=lambda u: u['logins'])
max здесь использует ключ — сам список логинов (не его длину). Python сравнивает списки лексикографически (поэлементно). Пустой список считается меньше непустого, поэтому макс возвращает объект с большим (в смысле лексикографического сравнения) списком — Bob.
Почему не будет TypeError
Иногда путают возможность ошибки при сравнении пустого списка. В данном случае TypeError не возникает: сравниваются списки строк, а строки сравниваются корректно. TypeError может появиться, если элементы списков нельзя сравнить друг с другом (например, различные несравнимые типы в Python 3), но это не наш случай.
Разбор вариантов (логика выбора)
- Вариант с "Ann Bob" соответствует фактическому выводу: min по длине выбирает Ann, max по списку — Bob.
- Другие варианты либо предполагают обратную логику ключей, либо ошибочно думают о
TypeError— оба неверны для данного входа.
Демонстрации и альтернативы
1) То же поведение на практике:

2) Если вы хотели выбрать пользователя с максимальным количеством логинов, используйте len и для max:

3) Если нужна детерминированность: сначала по длине, потом — по лексикографическому порядку списка:

Советы и подводные камни
- Внимательно проверяйте, что возвращает ключ (
key=). Частая опечатка — оставить список вместо его длины. - Сравнение списков — лексикографическое. Пустой список всегда меньше непустого.
- Если элементы списков могут быть разных типов (или несравнимы), сравнение списков может дать
TypeErrorпри сравнивании элементов. В таких случаях лучше явно задавать сравнимые кортежи в ключе. - Для читаемости предпочтительно использовать явные ключи (например,
len(u['logins'])) и, при необходимости, комментарии.
Вывод
Код печатает "Ann Bob" потому, что min использует длину списка логинов (и выбирает Ann с длиной 0), а max тут сравнивает сами списки логинов лексикографически (и выбирает Bob с непустым списком). Частая ошибка — смешивать типы ключей или забывать применить len — следите за этим и используйте кортежные ключи для детерминированного поведения.