Какое поведение ожидается при удалении элемента из пустого стека?
Что проверяют
Знаете ли вы, как ведут себя стандартные структуры Python на граничном случае и как вы проектируете ошибки в своём коде. Следом обычно просят написать pop для собственного класса стека или решить задачу на скобки, где пустой стек означает некорректный ввод.
Как отвечать
Начните с фактов о стандартной библиотеке:
list:[].pop()бросаетIndexError: pop from empty list, а чтение вершиныstack[-1]на пустом списке тоже бросаетIndexError, но с сообщением про выход за границы;collections.deque:pop()иpopleft()на пустой очереди тоже бросаютIndexError;queue.LifoQueue: потокобезопасный стек,get()на пустом по умолчанию блокируется и ждёт элемент, аget_nowait()илиget(block=False)бросаетqueue.Empty;asyncio.LifoQueue:await get()приостанавливает корутину,get_nowait()бросаетasyncio.QueueEmpty.
Для своего класса лучший вариант обычно исключение, а не None. Возврат None неоднозначен: в стеке может лежать настоящий None, и вызывающий код не отличит пустоту от значения. Разумно бросать IndexError или собственное исключение, унаследованное от него, тогда код, который ловит стандартную ошибку, продолжит работать. Если нужен мягкий вариант, сделайте его явным, по образцу dict.pop(key, default).
Проверка на стороне вызова в Python идиоматична в двух стилях. LBYL: if stack: stack.pop(), пустой список ложен, отдельный is_empty() не нужен. EAFP: try с except IndexError, удобно, когда пустота редкость. В алгоритмических задачах почти всегда пишут проверку, потому что пустой стек там не ошибка программы, а часть логики.
Где спотыкаются
Говорят, что pop() на пустом списке вернёт None. Не вернёт, это исключение, и программа упадёт, если его не поймать.
Ловят слишком широко: except Exception вокруг большого блока глушит заодно настоящие баги. Ловить стоит IndexError вокруг одной строки.
В задачах на скобки забывают проверить стек перед pop на закрывающей скобке и не проверяют его пустоту в конце. Тогда строка ")(" роняет решение, а "((" проходит как корректная.