如何在Python中创建用户定义类型断言?

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

如何创建一个以类似于

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 python-typing mypy
1个回答
3
投票

Mypy 通常只理解几种缩小类型的特定方法,例如使用

isinstance
if x is not None
。然而,在 Python >=3.10 中,PEP 647 通过新的
typing.TypeGuard
功能提供了此问题的解决方案。现在,您可以像这样编写
ComplexTypeAssertion
函数,并且类型检查器将理解,如果函数返回
data
,则
list[str]
保证为
True
类型:

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
也可用于 PyPI<3.10 via the semi-official 上的 Python
typing-extensions
库,它提供了较新类型构造到早期版本 Python 的反向移植。 (如果您使用 Mypy,您会发现
typing-extensions
已经是 Mypy 的依赖项,因此从
typing-extensions
导入某些内容甚至不一定意味着您必须向项目添加额外的依赖项。)

© www.soinside.com 2019 - 2024. All rights reserved.