在类型中使用泛型将参数描述为具体类以及这些类的实例

问题描述 投票:0回答:1

由于我必须不断验证类属性(可比较),因此将其放入或多或少通用的描述符中似乎是明智的,该描述符应该验证所设置的参数类型和值的范围(如果可以接受)。

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):
        …

如何表达:

  1. type_
    属性是一个类。

  2. start_value
    和end_value是在
    type_
    属性中指定的类的实例。

因此 - 然后我可以为方法

set_name
get
set
等方法的参数指定类型约束。

我尝试使用打字文档来解决这个问题,但我仍然不清楚。

python generics typing
1个回答
0
投票

为了满足您的要求,您可以简化

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
© www.soinside.com 2019 - 2024. All rights reserved.