首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用Python进行静态类型分析

用Python进行静态类型分析
EN

Stack Overflow用户
提问于 2020-02-18 11:49:43
回答 2查看 2.4K关注 0票数 3

有人能解释一下为什么这段代码虽然有效,却让类型的静态分析器以多种方式抱怨:

代码语言:javascript
运行
复制
ranges = dict()
ranges['max'] = 0
ranges['services'] = []
ranges['services'].append('a')

即:

代码语言:javascript
运行
复制
error: Incompatible types in assignment (expression has type "List[<nothing>]", target has type "int")

error: "int" has no attribute "append"

如果我简单地向ranges: dict = dict()的初始变量添加一个类型提示,它就会工作得很好。

我很困惑为什么静态分析器不能自己解决这个问题,特别是当我首先使用dict关键字初始化dict的时候。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-02-18 12:17:31

字典通常用作键集,最重要的操作是查找与任意键关联的值。通常,在字典中,每个键都有相同的类型,每个值都有相同的类型;如果值是异构的,那么表达式ranges[key]就不一定有特定的类型(尽管可以将它表示为一个联合)。

在您的代码中,静态分析器试图推断您的字典的类型。它所期望的类型是Dict[K, V]形式,其中KV尚未确定。第一个任务ranges['max'] = 0给出了关于两个未知数的信息:K似乎是strV似乎是int。因此,此时,ranges被推断为Dict[str, int]类型。

接下来的两行会出现错误,因为空列表不能用作Dict[str, int]中的值,而来自Dict[str, int]的值没有append方法。

显式类型注释ranges: dict = dict()通过指定这是一个异构字典来推翻默认行为,因此这些值不必都具有相同的类型。考虑到这些信息,静态分析器并不认为因为其中一个值是int,所以它们都必须是int的。

票数 5
EN

Stack Overflow用户

发布于 2020-02-18 12:35:30

由于您没有提供任何注释,mypy必须尝试推断这些类型。它可以作出一些选择:

  • ranges = dict()暗示range: Dict[Any, Any]

这将接受您所有的代码。它还将接受ranges['services'].keys()或任何其他操作,因为它删除了所有类型信息.

  • ranges['max'] = 0暗示range: Dict[str, int]

这就是mypy选择的内容。它拒绝任何非整数的值,特别是list.。

  • ranges['services'] = []暗示range: Dict[str, list]

这只接受您的ranges['services']字段。考虑到它不是list.,那么ranges['max']是无效的。

  • ranges['max'] = 0ranges['services'] = []意味着range: Dict[str, Union[int, list]]

它接受值的赋值。它拒绝ranges['services'].append('a'),因为ranges['services']可能是一个ranges['services']

基本上,这些都不起作用。使用普通的Dict[K, V],您的代码不能很好地键入。

您可以使用typing.TypedDict显式注释ranges。由于dict通常不限于静态键值对,所以mypy不会自己推断这一点。

代码语言:javascript
运行
复制
class Ranges(TypedDict):
    max: int
    services: List[str]

ranges: Ranges = dict()
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60280254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档