【问题标题】:Can mypy track string literals?mypy 可以跟踪字符串文字吗?
【发布时间】:2020-09-14 21:02:02
【问题描述】:

有没有办法让这个工作

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


bar = "bar"
foo(bar)

这里是错误

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

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

【问题讨论】:

  • 我对Python类型的了解不多,但是一旦赋值给一个变量,我认为它不再是文字了;这是一个str 对象。

标签: python mypy


【解决方案1】:

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

mypy Docs » Literal types

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

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

from typing import Final

from typing_extensions import Final

bar: Final = "bar"
reveal_type(bar)  # Revealed type is 'Literal['bar']?'

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

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

reveal_type([bar])  # Revealed type is 'builtins.list[builtins.str*]'

【讨论】:

  • 是否可以使用类似的方法让 mypy 将列表文字解释为 ["a", "b"],而不是 list[Literal["a", "b"]] 而不是 list[str]
  • @BallpointBen 您可以使用list[Literal['a', 'b']] 来获得builtins.list[Union[Literal['a'], Literal['b']]] 的显示类型,但如果位置很重要,您应该使用tuple[Literal['a'], Literal['b']]
猜你喜欢
  • 1970-01-01
  • 2010-10-12
  • 1970-01-01
  • 2019-07-17
  • 2015-03-21
  • 2013-06-23
  • 2018-05-03
  • 2013-09-04
  • 1970-01-01
相关资源
最近更新 更多