Python函数使用**kwargs时的参数合法性校验最佳实践咨询
Python 限定**kwargs允许传入参数的最佳实践
针对你明确仅允许传入cw、latlon两个参数的场景,优先推荐以下方案,按易用性和可维护性从高到低排序:
- 方案1:完全舍弃**kwargs,显式声明允许的参数
这个是最推荐的做法,不需要自己写任何参数校验逻辑,Python解释器原生会拦截非法参数,同时IDE能正常做参数补全和类型提示,代码可读性最高。
示例代码:
from typing import Optional, Any pr_label = ['PAN', 'SWIR', 'VNIR'] def get(pr_type: str, cw: Optional[Any] = None, latlon: Optional[Any] = None): if not isinstance(pr_type, str) or str(pr_type).upper() not in pr_label: raise TypeError(f'pr_type: {pr_type}, not valid.') # 后续可以直接判断cw、latlon是否为None来处理传参逻辑 # TODO: foo
如果用户传入了cw、latlon之外的参数,Python会直接抛出TypeError: get() got an unexpected keyword argument 'xxx',完全不需要自己实现校验。
- 方案2:若必须保留**kwargs(比如需要透传部分参数到下层函数),用集合操作简化校验逻辑
你当前的循环校验可以简化为集合差集判断,代码更简洁,执行效率也更高:
pr_label = ['PAN', 'SWIR', 'VNIR'] key_fun_get = {'cw', 'latlon'} def get(pr_type: str, **kwargs): if not isinstance(pr_type, str) or str(pr_type).upper() not in pr_label: raise TypeError(f'pr_type: {pr_type}, not valid.') # 校验非法参数,兼容原逻辑的小写匹配 extra_keys = {k.lower() for k in kwargs} - key_fun_get if extra_keys: raise TypeError(f'parameter: {", ".join(extra_keys)}, not valid.') # 如果需要过滤合法参数往下传,可以用:valid_kwargs = {k:v for k,v in kwargs.items() if k.lower() in key_fun_get} # TODO: foo
- 方案3:多函数复用校验逻辑的场景,使用装饰器封装
如果项目中多个函数都需要做kwargs参数限定,可以把校验逻辑封装成装饰器,避免重复代码:
from typing import Set, Callable from functools import wraps pr_label = ['PAN', 'SWIR', 'VNIR'] def allow_kwargs(allowed_keys: Set[str], case_insensitive: bool = True): def decorator(func: Callable) -> Callable: @wraps(func) def wrapper(*args, **kwargs): check_keys = {k.lower() for k in kwargs} if case_insensitive else set(kwargs.keys()) extra_keys = check_keys - allowed_keys if extra_keys: raise TypeError(f'parameter: {", ".join(extra_keys)}, not valid for {func.__name__}.') return func(*args, **kwargs) return wrapper return decorator @allow_kwargs(allowed_keys={'cw', 'latlon'}) def get(pr_type: str, **kwargs): if not isinstance(pr_type, str) or str(pr_type).upper() not in pr_label: raise TypeError(f'pr_type: {pr_type}, not valid.') # TODO: foo
内容的提问来源于stack exchange,提问作者Gianni Spear
相关产品推荐
相关产品推荐

