当前位置: 首页 > 知识库问答 >
问题:

在Python 3.6中,在运行时根据联合类型检查变量

华星剑
2023-03-14

我试图编写一个函数装饰器,它使用Python 3.6类型提示来检查参数字典是否尊重类型提示,如果没有清晰描述问题,则会产生错误,用于HTTP API。

问题是,当函数有一个使用Union类型的参数时,我无法在运行时对照它检查变量

比如我有这个功能

from typing import Union
def bark(myname: str, descr: Union[int, str], mynum: int = 3) -> str:
    return descr + myname * mynum

我可以做到:

isinstance('Arnold', bark.__annotations__['myname'])

但不是:

isinstance(3, bark.__annotations__['descr'])

因为Union不能与is实例issubclass一起使用。

我找不到使用type对象检查它的方法。我试图自己实现检查,但当吠叫时。__annotations__['desr']显示为键入。在REPL中的Union[int, str]我不能在运行时访问类型列表,如果不使用检查bark的丑陋黑客。__annotations__['desr']。__repr__()

是否有适当的方式访问此信息?还是故意让它在运行时不易访问?

共有3个答案

澹台俊材
2023-03-14

MSeifert接受的现有答案(https://stackoverflow.com/a/45959000/7433423)不会将Unions与其他泛型类型区分开来,并且由于参数化Union类型上的isinstance()issubclass()的行为,在运行时很难确定类型批注是Union还是其他泛型类型,如Mapping

似乎泛型类型将具有一个未记录的__origin__属性,该属性将包含对用于创建它的原始泛型类型的引用。一旦您确认类型注释是参数化的Union,您就可以使用也未记录的__args__属性来获取类型参数。

>>> from typing import Union
>>> type_anno = Union[int, str]
>>> type_anno.__origin__ is Union
True
>>> isinstance(3, type_anno.__args__)
True
>>> isinstance('a', type_anno.__args__)
True
梁盛
2023-03-14

您可以使用Union__args__属性,其中包含可能内容的元组

>>> from typing import Union

>>> x = Union[int, str]
>>> x.__args__
(int, str)
>>> isinstance(3, x.__args__)
True
>>> isinstance('a', x.__args__)
True

\uuuu args\uuuu参数没有文档化,因此可以认为它“弄乱了实现细节”,但它似乎比解析repr更好。

李昌勋
2023-03-14

在Python3.8及更高版本中,MSeifert和Richard Xia建议的方法可以通过不使用未记录的属性\uuuuuu origin\uuuu\uuu args\uuu来改进。此功能由新函数键入提供。获取参数(tp)键入。获取原点(tp)

>> from typing import Union, get_origin, get_args
>> x = Union[int, str]
>> get_origin(x), get_args(x)
(typing.Union, (<class 'int'>, <class 'str'>))
>> get_origin(x) is Union
True
>> isinstance(3, get_args(x))
True
>> isinstance('a', get_args(x))
True
>> isinstance([], get_args(x))
False

附言:我知道这个问题是关于Python 3.6的(可能是因为这是当时最新的版本),但是当我作为Python 3.8用户搜索解决方案时,我来到了这里。我想其他人可能也有同样的情况,所以我认为在这里增加一个新的答案是有意义的。

 类似资料:
  • 问题内容: 更新(2020年9月) :Python 3.9包含此用例的功能,请参阅https://docs.python.org/3.9/library/typing.html#typing.get_type_hints 我正在尝试编写一个使用Python 3.6类型提示的函数装饰器,以检查参数字典是否尊重类型提示,并且如果未出现带有问题清晰说明的错误,则将其用于HTTP API。 问题是,当函数

  • 问题内容: 我几乎没有这样声明的C函数 我想将这些作为一个Go函数公开 所以我需要能够在运行时检查 参数 类型。我该怎么做,这是个好主意吗(如果不是,在这种情况下,什么是好的做法)? 问题答案: 在此处查看类型断言: http://golang.org/ref/spec#Type_assertions 我只断言一个明智的类型(字符串,uint64)等,并使其尽可能宽松,最后执行到本机类型的转换。

  • 我试图找到一种方法来传递一个对象来发挥作用,并在运行库中检查它的类型。这是一个伪代码: 但是总是返回,我无法找到获取或的真正类型的方法。也不起作用,返回了相同的内容。

  • 我在android和Kotlin有奇怪的问题。问题是我用类型定义变量,但在运行时更改为 我这样定义我的变量: 我使用kotlin 1.3.71和jvm 1.8。 更新0:

  • 是否有可能创建一个typeGuard,或者其他实现相同目的的东西,来检查一个变量是否是打字稿联合中的特定接口类型?

  • 问题内容: 假设通用类型声明(Java) 我如何在运行时实例化一个Type对象,该对象表示通过特定类型T(也仅在运行时才知道)进行参数化的Foo? 问题答案: 我想我明白你的问题。您想要序列化一个,并且在运行时具有class对象(但在编译时不是固定的)。因此,在Gson中建议的创建匿名子类的解决方案不起作用,因为这要求在编译时对参数化类型(例如)进行硬编码,并且如果使用,则该解决方案不起作用。 但