假设我有一个python函数,它的单个参数是一个非平凡类型:
from typing import List, Dict
ArgType = List[Dict[str, int]] # this could be any non-trivial type
def myfun(a: ArgType) -> None:
...
.然后我有一个数据结构,我已经从JSON源解压缩:
import json
data = json.loads(...)
我的问题是:在将data
用作myfun()
的参数之前,我如何在运行时检查data
是否有正确的类型用作myfun()
的参数?
if not isCorrectType(data, ArgType):
raise TypeError("data is not correct type")
else:
myfun(data)
7条答案
按热度按时间bmp9r5qi1#
验证类型注解是一项重要的任务。Python不会自动执行此操作,而且编写自己的验证器也很困难,因为
typing
模块没有提供太多有用的接口。(事实上,自从python 3.5引入typing
模块以来,它的内部已经发生了很大的变化,以至于它真的是一场噩梦。下面是一个类型验证器函数,来自我的一个个人项目(代码墙警告):
演示:
(As据我所知,它支持所有python版本,甚至是使用
typing
module backport的<3.5版本。vql8enpb2#
很尴尬的是,没有内置的函数,但
typeguard
附带了一个方便的check_type()
函数:更多信息请参见:https://typeguard.readthedocs.io/en/latest/api.html#typeguard.check_type
bd1hkmkf3#
首先,尽管我认为你已经意识到了,但为了完整起见,类型库包含了类型提示的类型。IDE使用这些类型提示来检查您的代码是否合理,并且还可以作为开发人员期望的类型的文档。
要检查变量是否是某个类型,我们必须使用isinstance函数。令人惊讶的是,我们可以使用类型库函数的直接类型,例如。
然而,对于嵌套结构,如
List[Dict[str, int]]
,我们不能直接使用它,因为你会得到一个TypeError。你要做的是:1.检查初始值是否为列表
1.检查列表中的每一项是否为dict类型
1.检查每个dict的每个键是否都是字符串,每个值是否都是int
不幸的是,对于严格的检查,python有点麻烦。但是,请注意Python使用了duck类型:如果它像一只鸭子,行为也像一只鸭子,那么它肯定是一只鸭子。
vhmi4jdf4#
处理这种情况的常用方法是利用这样一个事实,即如果传递给
myfun
的对象没有所需的功能,则会引发相应的异常(通常是TypeError
或AttributeError
)。因此,您可以执行以下操作:你在问题中指出,如果传递的对象没有适当的结构,你会引发
TypeError
,但Python已经为你做了这件事。关键问题是你将如何处理这个案子。如果合适的话,还可以将try / except
块移动到myfun
中。在Python中输入时,你通常依赖duck typing:如果对象具有所需的功能,那么你不太关心它是什么类型,只要它服务于目的。请看下面的例子。我们只需将数据传入函数,然后免费获得
AttributeError
(然后我们可以排除);无需手动类型检查:如果您担心所产生的错误的有用性,您仍然可以except然后重新引发自定义异常(甚至更改异常的消息):
当使用第三方代码时,应该始终检查文档中将引发的异常。例如,
numpy.inner
报告在某些情况下将引发ValueError
。当使用该函数时,我们不需要自己执行任何检查,而是依赖于它会在需要时引发错误的事实。当使用第三方代码时,不清楚它在某些情况下的行为,i.m.o.硬编码一个相应的类型检查器(见下文),而不是使用适用于任何类型的通用解决方案,这更容易和更清楚。这些情况应该是罕见的,无论如何,留下相应的评论,使您的同胞开发人员意识到这种情况。typing
库用于类型提示,因此它不会在运行时检查类型。当然,你可以手动完成,但这是相当麻烦的:这与适当的注解一起仍然是一个可接受的解决方案,并且在需要类似数据结构的情况下可以重用。意图很清楚,代码很容易验证。
tzcvj98z5#
你必须手动检查你的嵌套类型结构--类型提示是不强制的。
像这样的检查最好使用ABC(Abstract Meta Classes)-这样用户就可以提供支持与默认dict/lists相同访问的派生类:
输出量:
多库:
相关信息:
另一种方法是遵循"Ask forgiveness not permission" - explain范式,简单地以您想要的形式使用您的数据,如果它不符合您想要的格式,则使用
try:/except:
。这更适合What is duck typing?-并允许(类似于ABC检查)消费者为您提供从list/dict派生的类,而它仍然可以工作。7kjnsjlb6#
如果你想做的只是json解析,你应该只使用pydantic。
但是,我遇到了同样的问题,我想检查python对象的类型,所以我创建了一个比其他答案更简单的解决方案,至少处理嵌套列表和字典的复杂类型。
我用这个方法在https://gist.github.com/ramraj07/f537bf9f80b4133c65dd76c958d4c461上创建了一个gist
该方法的一些示例使用包括:
下面的代码可供参考:
8qgya5xd7#
您可以从
trycast
模块中使用isassignable
函数,该模块正是为此类用例设计的。isassignable(value, T)
类似于Python的内置isinstance()
,但还支持检查任意类型的注解对象,包括 TypedDicts、Unions、Literals 和许多其他类型