mypy 可以跟踪字符串文字吗?

gec*_*kos 3 python mypy

有没有办法让这项工作

from typing import Literal
def foo(bar: Literal["bar"]) -> Literal["foo"]:
    foo = "foo"
    return foo


bar = "bar"
foo(bar)
Run Code Online (Sandbox Code Playgroud)

以下是错误

foo.py:4: error: Incompatible return value type (got "str", expected "Literal['foo']")
foo.py:8: error: Argument 1 to "foo" has incompatible type "str"; expected "Literal['bar']"
Run Code Online (Sandbox Code Playgroud)

很明显,foo变量和bar是文字,因为它们被分配给文字,所以这是安全的,但 mypy 似乎没有跟踪这一点。有什么我想念的吗?

Mis*_*agi 5

MyPy 将文字推断为它们的内置类型,而不是Literal它们的值。

mypy文档 » 文字类型

您必须显式地向变量添加注释以声明它具有文字类型。[..] 没有这个注解的变量不被假定为文字。

要允许推断Literal值,请将变量注释为Final

from typing import Final

from typing_extensions import Final

bar: Final = "bar"
reveal_type(bar)  # Revealed type is 'Literal['bar']?'
Run Code Online (Sandbox Code Playgroud)

将变量注释为Final表示它的值不会替换为类似类型的值。这使得将类型推断为特定Literal值是正确的,而不仅仅是一般类型。

请注意,此推断是上下文相关的:Literal对于Literal预期为 a 的所有情况,都会推断出类型。对于需要类型的情况,无论是文字类型、基类型还是 TypeVar,都会将该类型推断为通用类型。

reveal_type([bar])  # Revealed type is 'builtins.list[builtins.str*]'
Run Code Online (Sandbox Code Playgroud)

  • 哇,这真的很糟糕......它使得文字类型使用起来真的很烦人。看起来 Pyright 已经完美地做到了这一点。我想知道 mypy 是否对此有原则立场,或者这只是目前的技术限制。 (3认同)
  • 是否可以使用类似于 get mypy 的方法来解释列表文字,例如 `["a", "b"]`,如 `list[Literal["a", "b"]]` 而不是 `list[ str]`? (2认同)