简体   繁体   English

如果变量通过某些测试,则断言它具有某些属性

[英]Asserting a variable has certain properties if it passes certain tests

Using the python typing system, I sometimes know the type of a variable or an expression because I have installed runtime checking to verify it.使用 python 类型系统,我有时可以知道变量或表达式的类型,因为我已经安装了运行时检查来验证它。 Is there a way to denote this with annotations?有没有办法用注释来表示这个?

For example, suppose I have a function combop which returns True if its argument is of class Combination .例如,假设我有一个 function combop ,如果它的参数是 class Combination则返回True And further suppose that the class Combination has a field called tds .并进一步假设 class Combination有一个名为tds的字段。

if combop(x):
   return f(x.tds)
else:
   return f([])

In this example, I'd like to promise the checker that within the then part of the if, that x has type Combination , and x.tds makes sense.在这个例子中,我想要 promise 检查器,在 if 的 then 部分中, x的类型为Combination ,并且x.tds有意义。

An example of such a situation is line 172 of here python-rte .这种情况的一个例子是此处 python-rte的第 172 行。 The IDE complains about d.tds and also ns . IDE 抱怨d.tdsns I am supposing that there is a way to explain my intentions with type annotations, and the IDE would accept or verify my claim if possible.我假设有一种方法可以用类型注释来解释我的意图,如果可能的话,IDE 会接受或验证我的主张。

The way this is done in some functional languages (eg Scala) is with pattern matching.在某些函数式语言(例如 Scala)中,这样做的方式是使用模式匹配。 Within a clause of a pattern match the type inferencer is able to restrict the type of certain variables.在模式匹配的子句中,类型推断器能够限制某些变量的类型。 In some other languages (eg Common Lisp) there is a declare syntax which allows the programmer to give hints to the type inferencer which may or may not contribute a run-time overhead, depending on compiler settings.在其他一些语言(例如 Common Lisp)中,有一种declare语法,允许程序员向类型推断器提供提示,这可能会或可能不会增加运行时开销,具体取决于编译器设置。

Python 3.10 will introduce the new TypeGuard feature, which might provide you with what you're looking for. Python 3.10 将引入新的TypeGuard功能,它可能会为您提供您正在寻找的东西。 (The feature is also available through the typing_extensions module for Python <= 3.9.) A TypeGuard allows you to assert to the type-checker that an object is of a certain type. (该功能也可通过 Python <= 3.9 的typing_extensions模块获得。) TypeGuard允许您向类型检查器断言 object 是某种类型。 So, you could write a function like this:所以,你可以这样写一个 function:

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`.

If you're more interested in the properties of your object (the "structural type" as opposed to the "nominal type" of your object), then you could use a TypeGuard to assert that your object conforms to a certain protocol .如果您对 object 的属性(“结构类型”而不是对象的“标称类型”)更感兴趣,那么您可以使用TypeGuard断言您的 object 符合某个协议

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`.

As this is a new feature in the python-typing world, Python's major type-checkers are still working on support for this feature, especially with respect to some complex corner cases .由于这是 python 类型世界中的一项新功能,Python 的主要类型检查器仍在努力支持此功能,尤其是在一些复杂的极端情况下

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"

I used MyPy to reproducibly check, but my IDE PyCharm also understands it: when I hover the variable name I assigned the expression to, it says that the first one is of type Union[list, Foo] while the second is of type Foo .我使用 MyPy 进行可重复检查,但我的 IDE PyCharm 也理解它:当我 hover 我将表达式分配给的变量名时,它说第一个是Union[list, Foo]类型,而第二个是Foo类型。

More info: see the docs更多信息:查看文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM