在 Python 中,如何(是否应该)实现模型一致性?我想通过添加一些一致性检查来增强我的模型实现(例如,值不能为负,这个值不能为 None 等)。我想知道是否可以添加一些“类型检查”式的检查,例如检查我放入汽车的对象是否真的是方向盘。我希望执行某种类型检查,以便尽快发现错误。我希望在我将合适的转向轮放入汽车时就能够知道,而不是当汽车第一次转弯时(然后一路调试,直到找到错误的赋值)。我读到,根据 Python 的鸭子类型哲学,检查添加的对象的属性或方法而不是它的类型更为合适。我理解这一原则,但这意味着模型必须知道如何使用该对象才能检查给定对象是否正确,并且会在模型和控制器之间创建错误的依赖关系。此外,应该测试哪些属性?wheel.rotate() 可以适用于方向盘,也可以适用于轮胎。另一种方法是保持模型不变,并用 try-catch 环绕模型对象的每次使用,期待出现 AttributeError 或 TypeError,但这会非常麻烦。也许我想要这个是错的,如果有人能说服我我弄错了,那就太好了。但如果你认为我有权要求模型在变得不一致时引发错误,你能否告诉我一种除了使用 isinstance() 之外的其他方法?
2、解决方案
我们可以使用一个装饰器来检查函数的输入和输出类型,如果类型不匹配,就抛出异常。如果函数没有指定输入类型,则默认检查输入类型是否为 None。如果函数没有指定输出类型,则默认检查输出类型是否为 None。
from typing import Any, Callable, Type
def type_check(input_type: Type[Any] = None, output_type: Type[Any] = None) -> Callable:
"""
检查函数的输入和输出类型。
Args:
input_type: 函数的输入类型。
output_type: 函数的输出类型。
Returns:
一个装饰器函数。
"""
def decorator(func: Callable) -> Callable:
"""
装饰器函数。
Args:
func: 要装饰的函数。
Returns:
装饰后的函数。
"""
def wrapper(*args: Any, **kwargs: Any) -> Any:
"""
装饰器的包装函数。
Args:
*args: 函数的参数。
**kwargs: 函数的关键字参数。
Returns:
函数的返回值。
"""
# 检查输入类型
if input_type is not None:
for arg in args:
if not isinstance(arg, input_type):
raise TypeError(f"Invalid input type: {type(arg)}")
# 检查输出类型
if output_type is not None:
result = func(*args, **kwargs)
if not isinstance(result, output_type):
raise TypeError(f"Invalid output type: {type(result)}")
return result
return wrapper
return decorator
@type_check(input_type=int, output_type=int)
def add(a: int, b: int) -> int:
"""
两个整数的加法。
Args:
a: 第一个整数。
b: 第二个整数。
Returns:
两个整数的和。
"""
return a + b
# 测试
result = add(1, 2)
print(result) # 输出:3