A recommender scores the whole catalogue and then has to pick the handful it will actually show. Two things make that more than a sort: the scores are rarely unique, and you must not recommend something the user has already seen.
Task: write top_k(scores, k, already_seen) returning the chosen item ids, best first.
scores is a dictionary mapping item id to score.already_seen before ranking, not after. Filtering afterwards would leave you with fewer than k recommendations.k items — fewer if there aren't that many left after filtering, including none at all.The tie-break is what makes the output reproducible. Dictionary order would otherwise decide it, and that depends on how the dictionary was built rather than on anything about the items — which turns an A/B test into noise and makes a bug impossible to reproduce.
The neat way to do both at once is a sort key of (-score, item): Python compares tuples left to right, so the negated score sorts descending and the id breaks ties ascending, in one expression.