网站更新和维护怎么做,建筑局网站,wordpress是哪家公司的建站程序,设计师培训班费用目录 一、前置说明1、总体目录2、相关回顾3、本节目标 二、操作步骤1、项目目录2、代码实现3、测试代码4、日志输出 三、后置说明1、要点小结2、下节准备 一、前置说明
1、总体目录
《 pyparamvalidate 参数校验器#xff0c;从编码到发布全过程》
2、相关回顾
基于 Valid… 目录 一、前置说明1、总体目录2、相关回顾3、本节目标 二、操作步骤1、项目目录2、代码实现3、测试代码4、日志输出 三、后置说明1、要点小结2、下节准备 一、前置说明
1、总体目录
《 pyparamvalidate 参数校验器从编码到发布全过程》
2、相关回顾
基于 Validator 类实现 ParamValidator用于校验函数参数
3、本节目标
了解 __getattribute__ 的特性使用 __getattribute__ 结合 Validator 类中的方法让编辑器 Pycharm 智能提示 ParamValidator 类中的方法
二、操作步骤
1、项目目录 atme : me 用于存放临时的代码片断或其它内容。pyparamvalidate : 新建一个与项目名称同名的package为了方便发布至 pypi 。core : 用于存放核心代码。tests : 用于存放测试代码。utils : 用于存放一些工具类或方法。
2、代码实现
atme/demo/validator_v6/param_validator.py import inspect
from functools import wraps
from typing import TypeVar, Callablefrom atme.demo.validator_v6.validator import ValidatorSelf TypeVar(Self, boundParameterValidator)class ParameterValidator:def __init__(self, param_name: str, param_rule_desNone)::param param_name: 参数名:param param_rule_des: 该参数的规则描述self.param_name param_nameself.param_rule_des param_rule_desself._validators []def __getattribute__(self, name: str):__getattribute__ 在每次访问对象的属性时都会触发不管属性是否存在。通过重写 __getattribute__可以自定义属性的获取逻辑实现了对特定属性的直接访问param_name 、param_rule_des 、 _validators而对于其他属性则创建名为 validator_method 的函数将其作为属性返回如果获取到的属性名为 param_name 、param_rule_des 、 _validators , 则使用 object.__getattribute__(self, name) 直接获取对象的属性值。不对 self.param_name 、 self.param_rule_des 、 self._validators 做改变if name in [param_name, param_rule_des, _validators]:return object.__getattribute__(self, name)如果属性名不在上述列表中说明用户正在访问一个不存在的属性这时创建了一个函数 collect_validator_method以用户使用 ParamValidator(param).is_string(exception_msgparam must be string).is_not_empty() 为例代码执行过程如下:1. 当用户调用 ParamValidator(param).is_string(exception_msgparam must be string) 时2. 由于 is_string 方法不存在__getattr__ 方法被调用返回 validator_method 函数(此时未被调用)is_string 方法实际上是 validator_method 函数的引用3. 当执行 is_string(exception_msgparam must be string) 时is_string 方法被调用, 使用关键字参数传递 exception_msgparam must be string4. 实际上是执行了 validator_method(exception_msgparam must be string) , validator_method 函数完成调用后执行函数体中的逻辑- 向 self._validators 中添加了一个元组 (is_string, (), {exception_msg: param must be string})- 返回 self 对象5. self 对象继续调用 is_not_empty(), 形成链式调用效果此时的 validator_method 函数的引用就是 is_not_empty, 调用过程与 1-4 相同。def validator_method(*args, **kwargs):self._validators.append((name, args, kwargs))return selfreturn validator_methoddef __call__(self, func: Callable) - Callable:wraps(func)def wrapper(*args, **kwargs):# 获取函数的参数和参数值bound_args inspect.signature(func).bind(*args, **kwargs).argumentsif self.param_name in kwargs:# 如果函数被装饰且以关键字参数传值则从 kwargs 中取参数值value kwargs[self.param_name]else:# 如果函数被装饰且以位置参数传值则从 bound_args 中取参数值value bound_args.get(self.param_name)# 实例化 Validator 对象validator Validator(value, fieldself.param_name, rule_desself.param_rule_des)# 遍历所有校验器(注意这里使用 vargs, vkwargs避免覆盖原函数的 args, kwargs)for method_name, vargs, vkwargs in self._validators:# 通过 函数名 反射获取校验函数对象validate_method getattr(validator, method_name)# 执行校验函数validate_method(*vargs, **vkwargs)# 执行原函数return func(*args, **kwargs)return wrapper分隔符以下所有方法是从 Validator 类中复制过来目的是- 让编辑器如 Pycharm 智能提示 ParameterValidator 本类中可以使用的校验方法- 这些方法仅供 Pycharm 智能提示使用没有任何实际作用可以是def is_string(self, exception_msgNone) - Self:...也可以是def is_string(self, exception_msgNone) - Self:return isinstance(self.value, str) - ParameterValidator 类的实例通过 __getattribute__ 方法动态收集用户的调用方法- 然后使用 __call__ 方法反射调用 Validator 类中的调用方法在模块中定义了: Self TypeVar(Self, boundParameterValidator)目的是- 方便从 Validator 类中复制校验方法粘贴之后不做任何代码层面的修改- 方便链式调用如 ParameterValidator(param).is_string().is_not_empty()def is_string(self, exception_msgNone) - Self:return isinstance(self.value, str)def is_not_empty(self, exception_msgNone) - Self:return bool(self.value)
3、测试代码
atme/demo/validator_v6/test_param_validator.py import pytestfrom atme.demo.validator_v6.param_validator import ParameterValidatordef test_is_string_validator_passing_01():校验一个参数ParameterValidator(param).is_string(exception_msgparam must be string)def example_function(param):print(param)return paramassert example_function(paramtest) testwith pytest.raises(ValueError) as exc_info:example_function(param123)print(exc_info.value)assert invalid in str(exc_info.value)def test_is_string_validator_passing_02():校验多个参数ParameterValidator(param2).is_string().is_not_empty()ParameterValidator(param1).is_string().is_not_empty()def example_function(param1, param2):print(param1, param2)return param1, param2assert example_function(test1, test2) (test1, test2)with pytest.raises(ValueError) as exc_info:example_function(123, 123)print(exc_info.value)assert invalid in str(exc_info.value)
4、日志输出
执行 test 的日志如下验证通过 test session starts
collecting ... collected 2 itemstest_param_validator.py::test_is_string_validator_passing_01 PASSED [ 50%]test
param error: 123 is invalid. due to: param must be stringtest_param_validator.py::test_is_string_validator_passing_02 PASSED [100%]test1 test2
param2 error: 123 is invalid. 2 passed in 0.01s 三、后置说明
1、要点小结
__getattribute__ 在每次访问对象的属性时都会触发不管属性是否存在。通过重写 __getattribute__可以自定义属性的获取逻辑实现了对特定属性的直接访问param_name 、param_rule_des 、 _validators而对于其他属性则创建名为 validator_method 的函数将其作为属性返回。从 Validator 类中复制过来的校验方法是为了让编辑器如 Pycharm 智能提示 ParameterValidator 本类中可以使用的校验方法没有任何实际作用。在模块中定义 Self TypeVar(Self, boundParameterValidator)方便链式调用如 ParameterValidator(param).is_string().is_not_empty() 。经过优化后Pycharm 可以正常智能提示可调用的校验方法
2、下节准备
validator 常用校验器的实现
点击返回主目录