由于我必须不断验证类属性(可比较),因此将其放入或多或少通用的描述符中似乎是明智的,该描述符应该验证所设置的参数类型和值的范围(如果可以接受)。
from typing import TypeVar
T = TypeVar("T", bound=type)
Instance = TypeVar("Instance", bound=T) # ???
class TypeAndValueValidator:
def __init__(
self,
type_: T = None,
start_value=None,
end_value=None,
include_start: bool = True,
include_end: bool = True,
):
self.type = type_
self.start_value = start_value
self.end_value = end_value
self.include_start = include_start
self.include_end = include_end
def __set_name__(self, owner, name):
…
def __get__(self, obj, obj_type=None):
...
def __set__(self, obj, value):
…
如何表达:
type_
属性是一个类。
start_value
和end_value是在type_
属性中指定的类的实例。
因此 - 然后我可以为方法
set_name
、get
、set
等方法的参数指定类型约束。
我尝试使用打字文档来解决这个问题,但我仍然不清楚。
为了满足您的要求,您可以简化
TypeAndValueValidator
类中类型约束的使用。您不需要第二个TypeVar
。相反,您可以使用 Type[T]
来表示生成 T
实例的类的类型(即类对象)。这是更新的实现:
from typing import Type, TypeVar, Optional
T = TypeVar("T")
class TypeAndValueValidator:
def __init__(
self,
type_: Optional[Type[T]] = None,
start_value: Optional[T] = None,
end_value: Optional[T] = None,
include_start: bool = True,
include_end: bool = True,
):
self.type = type_
self.start_value = start_value
self.end_value = end_value
self.include_start = include_start
self.include_end = include_end
def __set_name__(self, owner, name: str):
self.name = name
def __get__(self, obj, obj_type=None):
return getattr(obj, f"_{self.name}", None)
def __set__(self, obj, value: T):
if self.type is not None and not isinstance(value, self.type):
raise TypeError(f"{self.name} must be of type {self.type.__name__}")
if self.start_value is not None:
if (self.include_start and value < self.start_value) or (
not self.include_start and value <= self.start_value
):
raise ValueError(f"{self.name} must be >= {self.start_value}")
if self.end_value is not None:
if (self.include_end and value > self.end_value) or (
not self.include_end and value >= self.end_value
):
raise ValueError(f"{self.name} must be <= {self.end_value}")
setattr(obj, f"_{self.name}", value)
说明:
使用类型[T]:
type_
参数声明为 Optional[Type[T]]
。这意味着
接受一个类别(例如,int
、str
)或 None
。start_value
和 end_value
属于 Optional[T]
类型,这意味着它们必须
是指定 type_
类(如果提供)或 None
.在
__set__
中验证:
value
是否是 type_
的实例。(start_value
和 end_value
)。动态属性存储:
__set_name__
方法分配一个私有名称(_{name}
)来动态存储实际值。
使用示例:
class MyClass:
value = TypeAndValueValidator(int, start_value=10, end_value=20)
obj = MyClass()
obj.value = 15 # Works
obj.value = 25 # Raises ValueError: value must be <= 20