如果变量通过某些测试,则断言它具有某些属性
Asserting a variable has certain properties if it passes certain tests
使用 python 类型系统,我有时可以知道变量或表达式的类型,因为我已经安装了 运行时间检查来验证它。有没有办法用注释来表示这个?
例如,假设我有一个函数 combop
,如果它的参数是 class Combination
,它会 returns True
。并进一步假设 class Combination
有一个名为 tds
.
的字段
if combop(x):
return f(x.tds)
else:
return f([])
在此示例中,我想向检查器保证,在 if 的 then 部分中,x
的类型为 Combination
,并且 x.tds
有意义。
这种情况的一个例子是 here python-rte 的第 172 行。 IDE 抱怨 d.tds
和 n.s
。我假设有一种方法可以用类型注释来解释我的意图,并且 IDE 会在可能的情况下接受或验证我的主张。
在某些函数式语言(例如 Scala)中,这样做的方式是使用模式匹配。在模式匹配的子句中,类型推断器能够限制某些变量的类型。在其他一些语言(例如 Common Lisp)中,有一种 declare
语法,允许程序员向类型推断器提供提示,这可能会或可能不会贡献 运行 时间开销,具体取决于编译器设置。
import typing
class Foo:
def __init__(self) -> None:
self.bar = "zebra" # will be of 'str' type
def give_me_something(): # no annotation here, can't tell what gets returned
if dict(): # an empty dict is always False, this is just an example, a real condition could be used
return []
else:
return Foo()
reveal_type(give_me_something())
reveal_type(typing.cast(Foo, give_me_something()))
$ mypy so69205255.py
so69205255.py:16: note: Revealed type is "Any"
so69205255.py:17: note: Revealed type is "so69205255.Foo"
我使用 MyPy 进行了可重复检查,但我的 IDE PyCharm 也理解它:当我将鼠标悬停在我分配表达式的变量名称时,它说第一个是类型 Union[list, Foo]
而第二个是 Foo
.
类型
更多信息:参见 the docs
Python 3.10 将为 Python <= 3.9 引入新的 TypeGuard
feature, which might provide you with what you're looking for. (The feature is also available through the typing_extensions 模块。) TypeGuard
允许您向类型检查器断言一个对象是某种类型的。因此,您可以编写如下函数:
from typing import TypeGuard, Any
def combop(obj: Any) -> TypeGuard[Combination]:
# Some code that returns `True` if the object is of type `Combination`, else `False`.
如果您对对象的 属性 更感兴趣(“结构类型”而不是对象的“标称类型”),那么您可以使用a TypeGuard
断言您的对象符合某个 protocol.
from typing import Protocol, TypeGuard, Any
class CombinationsProto(Protocol):
tds: list[Any]
def combops(obj: Any) -> TypeGuard[CombinationsProto]:
# Some code here that returns `True` if the object has a `tds` attribute, else `False`.
由于这是 python 打字世界的一项新功能,Python 的主要类型检查器仍在努力支持此功能,特别是对于一些复杂的 corner cases.
使用 python 类型系统,我有时可以知道变量或表达式的类型,因为我已经安装了 运行时间检查来验证它。有没有办法用注释来表示这个?
例如,假设我有一个函数 combop
,如果它的参数是 class Combination
,它会 returns True
。并进一步假设 class Combination
有一个名为 tds
.
if combop(x):
return f(x.tds)
else:
return f([])
在此示例中,我想向检查器保证,在 if 的 then 部分中,x
的类型为 Combination
,并且 x.tds
有意义。
这种情况的一个例子是 here python-rte 的第 172 行。 IDE 抱怨 d.tds
和 n.s
。我假设有一种方法可以用类型注释来解释我的意图,并且 IDE 会在可能的情况下接受或验证我的主张。
在某些函数式语言(例如 Scala)中,这样做的方式是使用模式匹配。在模式匹配的子句中,类型推断器能够限制某些变量的类型。在其他一些语言(例如 Common Lisp)中,有一种 declare
语法,允许程序员向类型推断器提供提示,这可能会或可能不会贡献 运行 时间开销,具体取决于编译器设置。
import typing
class Foo:
def __init__(self) -> None:
self.bar = "zebra" # will be of 'str' type
def give_me_something(): # no annotation here, can't tell what gets returned
if dict(): # an empty dict is always False, this is just an example, a real condition could be used
return []
else:
return Foo()
reveal_type(give_me_something())
reveal_type(typing.cast(Foo, give_me_something()))
$ mypy so69205255.py
so69205255.py:16: note: Revealed type is "Any"
so69205255.py:17: note: Revealed type is "so69205255.Foo"
我使用 MyPy 进行了可重复检查,但我的 IDE PyCharm 也理解它:当我将鼠标悬停在我分配表达式的变量名称时,它说第一个是类型 Union[list, Foo]
而第二个是 Foo
.
更多信息:参见 the docs
Python 3.10 将为 Python <= 3.9 引入新的 TypeGuard
feature, which might provide you with what you're looking for. (The feature is also available through the typing_extensions 模块。) TypeGuard
允许您向类型检查器断言一个对象是某种类型的。因此,您可以编写如下函数:
from typing import TypeGuard, Any
def combop(obj: Any) -> TypeGuard[Combination]:
# Some code that returns `True` if the object is of type `Combination`, else `False`.
如果您对对象的 属性 更感兴趣(“结构类型”而不是对象的“标称类型”),那么您可以使用a TypeGuard
断言您的对象符合某个 protocol.
from typing import Protocol, TypeGuard, Any
class CombinationsProto(Protocol):
tds: list[Any]
def combops(obj: Any) -> TypeGuard[CombinationsProto]:
# Some code here that returns `True` if the object has a `tds` attribute, else `False`.
由于这是 python 打字世界的一项新功能,Python 的主要类型检查器仍在努力支持此功能,特别是对于一些复杂的 corner cases.