How to Validate Function Arguments in Python
Shows how to manually check argument types and values in a Python function, raising clear TypeError and ValueError messages.
Python code
26 linesdef calculate_area(length: float, width: float) -> float:
"""Calculate the area of a rectangle with manual type validation."""
if not isinstance(length, (int, float)) or isinstance(length, bool):
raise TypeError(f"length must be a number, got {type(length).__name__}")
if not isinstance(width, (int, float)) or isinstance(width, bool):
raise TypeError(f"width must be a number, got {type(width).__name__}")
if length <= 0 or width <= 0:
raise ValueError("length and width must be positive numbers")
return length * width
if __name__ == "__main__":
print(calculate_area(5.5, 3))
try:
calculate_area("5", 3)
except TypeError as e:
print(f"TypeError: {e}")
try:
calculate_area(0, 3)
except ValueError as e:
print(f"ValueError: {e}")
try:
calculate_area(True, 3)
except TypeError as e:
print(f"TypeError: {e}")
Output
16.5
TypeError: length must be a number, got str
ValueError: length and width must be positive numbers
TypeError: length must be a number, got bool
How it works
The function calculate_area uses isinstance to confirm each argument is an int or float, while explicitly excluding bool because bool is a subclass of int in Python. After type checks, value validation ensures positive inputs to prevent meaningless results. Raising TypeError for wrong types and ValueError for bad values follows Python's exception conventions and makes bugs obvious. The if __name__ == "__main__" guard lets the code run as a script while keeping the function importable. This manual approach works without third-party libraries and gives full control over error messages.
Common mistakes
- Forgetting that `bool` is a subclass of `int` in Python, so it passes `isinstance(x, int)` unless explicitly excluded
- Checking types but not values, allowing zero or negative numbers to pass through with confusing results
- Using `type(x) == int` instead of `isinstance()` which fails for subclasses and is less flexible
Variations
- Use `numbers.Number` from the numbers module to accept all numeric types, including Decimal and Fraction
- Use type hints with a runtime validator like Pydantic for deeper validation in larger projects
Real-world use cases
- Validating numeric inputs in a data processing script before performing calculations to avoid NaN or negative values.
- Checking configuration values in a CLI tool where mistyped flags could crash the application.
- Guarding a library's public API input arguments to fail fast and give clear errors to the caller.
Sponsored
More from Functions & basics
- Add Type Hints to Function Parameters and Return in Python easy
- Benchmark list append vs comprehension in Python easy
- Build a Context Manager in Python with contextlib.contextmanager easy
- Build a Progress Callback Function for Loops in Python easy
- Cache expensive function with lru_cache in Python easy
- Calculate Time Difference Across Time Zones in Python easy
Keep learning
Related tutorials and quizzes for this topic.