Python中函数与类的参数大小写强制规范及严格参数类型校验(排除布尔值)的简便实现方案问询
Hey there! Let's work through your two Python requirements step by step:
To enforce a consistent case standard (like all lowercase, snake_case, etc.) for function and class parameters, a decorator is the cleanest and most reusable approach. Here's a practical implementation:
Example: Enforce all lowercase parameter names
This decorator checks that all keyword arguments passed to a function or class follow lowercase naming, and raises a ValueError if any don't. It works seamlessly with regular functions and class __init__ methods:
def enforce_lowercase_params(func): def wrapper(*args, **kwargs): # Validate all keyword argument keys for param_name in kwargs: if not param_name.islower(): raise ValueError(f"Parameter '{param_name}' must be in lowercase") return func(*args, **kwargs) return wrapper # Apply to a function @enforce_lowercase_params def calculate_area(length: int, width: int): return length * width # Apply to a class @enforce_lowercase_params class Rectangle: def __init__(self, length: int, width: int): self.length = length self.width = width # Test cases calculate_area(length=5, width=3) # Runs successfully calculate_area(Length=5, width=3) # Raises ValueError: Parameter 'Length' must be in lowercase Rectangle(Length=5, width=3) # Throws the same validation error
If you need a different case standard (like camelCase or snake_case), just adjust the validation logic in the decorator—for example, use a regex to check for snake_case patterns.
Great question! Python's default type checking treats bool as a subclass of int, which is why add_integers(True, 2) works. Here are a few straightforward, low-fuss ways to enforce strict type matching:
1. Direct type check in the function (simplest for single functions)
Instead of isinstance(), use type(param) is int to ensure the argument is exactly an int (not a subclass like bool):
def add_integers(a: int, b: int) -> int: if type(a) is not int or type(b) is not int: raise TypeError(f"Arguments must be strictly integers (got {type(a).__name__} and {type(b).__name__})") return a + b # Test results add_integers(1, 2) # Returns 3 add_integers(True, 2) # Raises TypeError: Arguments must be strictly integers (got bool and int) add_integers("1", 2) # Raises TypeError: Arguments must be strictly integers (got str and int)
2. Reusable decorator for strict type checking
If you need this behavior across multiple functions, a decorator eliminates code duplication. It uses the function's type hints to validate arguments automatically:
import inspect from typing import get_type_hints def strict_type_check(func): type_hints = get_type_hints(func) sig = inspect.signature(func) def wrapper(*args, **kwargs): # Bind incoming arguments to the function's signature bound_args = sig.bind(*args, **kwargs).arguments # Validate each argument against its type hint for param_name, value in bound_args.items(): expected_type = type_hints.get(param_name) if expected_type and type(value) is not expected_type: raise TypeError(f"Parameter '{param_name}' must be {expected_type.__name__} (got {type(value).__name__})") return func(*args, **kwargs) return wrapper # Usage @strict_type_check def add_integers(a: int, b: int) -> int: return a + b # Same test outcomes as the direct check add_integers(1, 2) # 3 add_integers(True, 2) # TypeError add_integers("1", 2) # TypeError
3. Using typing.Annotated (Python 3.9+)
For more flexible, self-documenting validation, combine Annotated with a custom validator. This keeps type hints and validation logic tied together:
from typing import Annotated, get_type_hints import inspect def strict_int(value): if type(value) is not int: raise TypeError(f"Expected strict int, got {type(value).__name__}") return value # Define a reusable strict integer type StrictInt = Annotated[int, strict_int] def add_integers(a: StrictInt, b: StrictInt) -> int: # Validate arguments using the annotated rules type_hints = get_type_hints(add_integers, include_extras=True) sig = inspect.signature(add_integers) bound_args = sig.bind(*args, **kwargs).arguments for param_name, value in bound_args.items(): _, validator = type_hints[param_name] validator(value) return a + b
All these methods bypass Python's default subclass behavior and ensure only exact int types are accepted.
内容的提问来源于stack exchange,提问作者Joanthan Ahrenkiel-Frellsen

