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

时间:2020-09-14 00:47:00

标签: python mypy python-typing

在下面的示例中,为什么将变量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'

1 个答案:

答案 0 :(得分:2)

这归因于某些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]'