我正在尝试编写一个函数装饰器,它使用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
不能与isinstance
或issubclass
一起使用。
我找不到使用type对象检查它的方法,我试着自己实现检查,但是当bark.__annotations__['descr']
在REPL中显示为typing.Union[int, str]
时,我无法在运行时访问类型列表,如果不使用检查bark.__annotations__['descr'].__repr__()
的丑陋技巧的话。
是否有适当的方法来访问这些信息?或者是否有意使其在运行时不容易访问?
5条答案
按热度按时间lnvxswe21#
在Python 3.8及更高版本中,MSeifert和Richard Xia建议的方法可以通过不使用未文档化的属性
__origin__
和__args__
来改进。新函数typing.get_args(tp)
和typing.get_origin(tp)
提供了此功能:字符串
i86rm4rw2#
您可以使用
Union
的__args__
属性,该属性包含“可能的内容:字符串
__args__
参数没有文档记录,所以它可能被认为是“扰乱了实现细节”,但它似乎是比解析repr
更好的方法。xxslljrj3#
MSeifert(https://stackoverflow.com/a/45959000/7433423)现有的公认答案并没有将
Union
与其他泛型类型区分开来,并且由于isinstance()
和issubclass()
在参数化Union
类型上的行为,在运行时很难确定类型注解是Union
还是其他泛型类型(如Mapping
)。似乎泛型类型将有一个未记录的
__origin__
属性,该属性将包含对用于创建它的原始泛型类型的引用。一旦确认类型注解是参数化的Union
,您就可以使用同样未记录的__args__
属性来获取类型参数。字符串
gdrx4gfi4#
您可以使用
typeguard
模块,它可以与pip
一起安装。它为您提供了一个函数check_argument_types
或函数装饰器@typechecked
。它应该为您执行运行时类型检查:https://github.com/agronholm/typeguard字符串
如果你想检查单个变量的类型,你可以直接使用typeguard的
check_type
函数:型
本例中未使用
"arg"
和None
参数。请注意,check_type
函数未作为此模块的公共函数记录,因此其API可能会发生更改。z9smfwbn5#
我想联合不是一个类型本身,而是一个类型的描述。
但是我们可以简单地使用
type(Union)
来请求类型(在Python 2.7中也可以)字符串