【问题标题】:Mypy: Type of dict value doesn't change with assignment while type of variable doesMypy:dict值的类型不会随着赋值而改变,而变量的类型会改变
【发布时间】:2020-09-15 00:14:41
【问题描述】:

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

【问题讨论】:

    标签: python mypy python-typing


    【解决方案1】:

    这是由于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]'
    
    • mypy所谓的promotion of types

    例如,int 在运行时不是float 的子类型,但mypy 认为是这样。在任何需要float 的地方,都可以传递int(有时可能并不明显),尽管它不是它的子类型。

    • 为类属性简化Union
    class A:
        x: Union[bool, int, float]  
    
    reveal_type(A.x)  # Revealed type is 'builtins.float'
    

    这个结果是因为boolint 的子类型,而intmypy 提升为float

    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]'
    

    【讨论】:

    • 感谢您的详细回答,如果我有一些后续问题,我会在接受之前花一些时间审查这些概念。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-11
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-14
    相关资源
    最近更新 更多