【问题标题】:How to create a user-defined type assertion in Python?如何在 Python 中创建用户定义的类型断言?
【发布时间】:2021-11-21 23:48:41
【问题描述】:

如何以类似于isinstance 的方式创建一个缩小变量类型(用于静态类型检查器)的函数?

例如,ComplexTypeAssertion 只是在运行时缩小类型,而不是用于静态检查:

def MyFunction(myData: object) -> object:
  if isinstance(myData, list):
    reveal_type(myData)  # Revealed type is 'builtins.list[Any]'
  if ComplexTypeAssertion(myData):   # <<< How to make MyPy understand this?
    reveal_type(myData)  # Revealed type is 'builtins.object'

def ComplexTypeAssertion(data: object) -> bool:
    return isinstance(data, list) and all(isinstance(value, str) for value in data)

我如何定义ComplexTypeAssertion 以便静态分析工具能够理解该类型?

显然,这是一个玩具示例,现实生活中的示例会更复杂。在我想断言某些数据遵循TypedDict 构造或其他类型构造的情况下,这将非常有用。

【问题讨论】:

    标签: python type-hinting mypy python-typing


    【解决方案1】:

    Mypy 一般只了解几种特定的缩小类型的方法,例如使用isinstanceif x is not None。但是,在 Python >=3.10 中,PEP 647 使用新的typing.TypeGuard 功能为这个问题提供了解决方案。现在,您可以像这样编写您的 ComplexTypeAssertion 函数,并且类型检查器将理解,如果函数返回 True,则 data 保证是 list[str] 类型:

    from typing import TypeGuard
    
    def ComplexTypeAssertion(data: object) -> TypeGuard[list[str]]:
        return isinstance(data, list) and all(isinstance(value, str) for value in data)
    

    TypeGuard 也可通过半官方的typing-extensions library on PyPI 用于 Python typing-extensions 已经是 Mypy 的依赖项,因此从 typing-extensions 导入某些内容甚至不一定意味着您必须为您的项目添加额外的依赖项。)

    【讨论】:

    • 太棒了!通过将 typing-extensions 更新到 ~3.10,我也可以在以前的 Python 版本中使用 TypeGuard。
    • @PhilMacKay 太棒了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 2014-01-12
    • 1970-01-01
    • 2016-12-19
    相关资源
    最近更新 更多