Finding the largest number in a list is straightforward.
Finding the second largest number is more interesting—and forces you to think carefully about duplicates, constraints, and edge cases.
This challenge builds directly on earlier list-based problems and introduces a common real-world requirement: uniqueness matters.
Your Task
Write a function that returns the second largest unique number in a list of numbers.
Function Signature
def second_largest(numbers: list) -> int | float:
…
Rules
- The input must be a list.
- Every element in the list must be a number (
intorfloat). - The list must contain at least two unique numeric values.
- Raise a
TypeErrorif the input is invalid. - Raise a
ValueErrorif a second largest value does not exist.
Examples
second_largest([1, 2, 3]) → 2
second_largest([5, 5, 3, 1]) → 3
second_largest([-1, -5, -3]) → -3
second_largest([10, 8, 9, 9]) → 9
Invalid Input Examples
second_largest([1]) → ValueError
second_largest([2, 2, 2]) → ValueError
second_largest("123") → TypeError
second_largest([1, "2", 3]) → TypeError
second_largest(None) → TypeError
Hints (Optional)
- Think about how to handle duplicate values.
- You can solve this with sorting, but a loop-based solution works too.
- Make sure your function fails clearly and predictably when requirements are not met.


What These Tests Enforce
✔️ Correct handling of valid numeric lists
✔️ Duplicate values handled properly
✔️ At least two unique values required
✔️ Clear distinction between TypeError and ValueError
✔️ Defensive handling of bad input
This keeps the challenge:
- Predictable
- Interview-clean
- Beginner-friendly but rigorous
What This Challenge Teaches
- Working with unique values
- Input validation
- Defensive programming
- Handling constraints explicitly
- Thinking beyond the “obvious” solution
Bonus Challenges
- Solve this without sorting
- Return both the largest and second largest values
- Track the two largest values in a single pass
- Compare performance between approaches
Why This Matters
In real applications, data is often messy.
Writing code that defines its assumptions and handles edge cases correctly is far more valuable than code that only works for perfect input.
🔗 View reference solution on GitHub
(After you’ve tried the challenge)
👉Next Challenge → Check If a String Is a Palindrome
Want more practical Python challenges?
Subscribe to the Solve With Python newsletter and get new problems delivered to your inbox.