Mypy:dict值的类型不会随赋值而改变,而变量的类型却会随赋值而改变

问题描述

在下面的示例中,为什么将变量foo的类型设置为整数但变量bar["foo"]的类型却没有改变?

import typing as tp

foo: tp.Union[float,int]
D = tp.TypedDict("D",{"foo": tp.Union[float,int]})

foo = 123.45
bar = D(foo=123.45)

reveal_type(foo)  # main.py:9: note: Revealed type is 'builtins.float'
reveal_type(bar["foo"])  # main.py:10: note: Revealed type is 'builtins.float'

foo = int(foo)
bar["foo"] = int(bar["foo"])

reveal_type(foo)  # main.py:15: note: Revealed type is 'builtins.int'
reveal_type(bar["foo"])  # main.py:16: note: Revealed type is 'builtins.float'

解决方法

这归因于某些mypy功能:

  • 缩小Union的类型。

初始声明后的任何赋值都会缩小类型

x: Union[int,float]
x = 1.1
reveal_type(x)  # Revealed type is 'builtins.float'

但是mypy不会缩小分配中的类型:

x: Union[int,float] = 1.1
reveal_type(x)  # Revealed type is 'Union[builtins.int,builtins.float]'
  • promotion of types的{​​{1}}。

例如,mypy在运行时不是int的子类型,但是float认为是。尽管不是mypy的子类型,但只要在float处都可以传递int(有时可能并不明显)。

  • 简化Union的类属性
class A:
    x: Union[bool,int,float]  

reveal_type(A.x)  # Revealed type is 'builtins.float'

此结果是因为boolint的子类型,并且intfloat提升为mypy

在您的TypedDict示例中,有一个Union的简化形式,如下所示:

from typing import Union,TypedDict

D = TypedDict("D",{"x": Union[int,float]}) 
d: D
y: Union[int,float]

reveal_type(d["x"])  # Revealed type is 'builtins.float'
reveal_type(y)  # Revealed type is 'Union[builtins.int,builtins.float]'

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...