【问题标题】:Correct way use type hints / generics to describe arguments of type class ("type")正确的方式使用类型提示/泛型来描述类型类(“类型”)的参数
【发布时间】:2016-06-09 21:03:39
【问题描述】:

这似乎与Type Hinting: Argument Of Type Class 相似,但是,那里接受的答案实际上并没有回答我的问题,所以问题可能表达不正确(?)

我有一个序列化/反序列化框架,可以从 [IDE 支持的] 类型提示中受益匪浅。 API 如下所示:

def serialize(obj:BaseModel) -> Dict[str,Any]:
    """ Serialize the object to a dictionary. """

def deserialize(data:Dict[str,Any], clazz:type) -> BaseModel:
    """ Deserialize dictionary into a model object of type clazz. """

序列化方法很好,但反序列化类型提示不是最佳的。我想指出反序列化的返回值将是clazz 类型的对象(它是BaseModel 的子类)。这似乎是泛型可以提供帮助的东西,但我不确定如何表达我想要的。

T = TypeVar('T', bound=BaseModel)

def deserialize(data:Dict[str,Any], clazz:T) -> T:
    """ Deserialize dictionary into a model object of type clazz. """

这似乎是错误的,因为 clazz 是从 T 派生的 而不是 T 类型的 对象(实例)。

我已经阅读了一些内容,但没有找到答案(谷歌搜索这个特定问题也很棘手)。是否有一些明显的我在这里遗漏了,或者这只是 python 3.5 输入模块不支持?

当然,我仍然受制于推断类型的工具,但希望如果有正确的方法可以做到这一点,它将由类型检查实用程序实现。

【问题讨论】:

    标签: python python-3.x generics type-hinting


    【解决方案1】:

    由于一个类可以被认为是一个返回的可调用对象和自身的实例,也许你可以试试:

    T = TypeVar('T', bound=BaseModel)
    
    def deserialize(data: Dict[str, Any], clazz: Callable[..., T]) -> T:
        """ Deserialize dictionary into a model object of type clazz. """
    

    省略号 (...) 表示类的调用签名未指定。所以一个可调用对象接受未指定的参数并返回T 的实例。

    【讨论】:

    • 啊,这是一个非常有趣的想法。我会试试的。 (尽管在我输入后立即意识到我的目标之一是让我的类型检查器验证类属性和 [class] 方法,这似乎会因为这个提示而丢失。)
    • 我认为您可以这样做,但您可以将其作为T 规范的一部分——通过指定其界限。您仍然可以对类进行运行时检查——这样类就具有数据所需的所有字段,但这超出了静态类型检查器的范围。
    • 我玩过这个。虽然 pycharm 目前似乎不支持 Callable,但这似乎是解决这个问题的最佳(唯一真正的?)解决方案。
    【解决方案2】:

    您可能会因为 Python 和类型检查器之间的脱节而变得有点棘手:

    T = TypeVar('T', bound=BaseModel)
    
    def deserialize(etc, T:type) -> T:
    

    那么T 既是您的参数名称,也是您的返回类型。我不知道您的 IDE 是否足够聪明,可以得到这个,或者生气到足以反感它。 ;-)

    【讨论】:

      猜你喜欢
      • 2020-10-24
      • 1970-01-01
      • 2021-05-01
      • 2017-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      • 1970-01-01
      相关资源
      最近更新 更多