Mypy 无法从文字列表中推断出项目的类型

Mypy can't infer the type of items from a list of Literals

我有一个变量 x 和一个文字列表(比如 0、1、2)。我想将 x 转换为这些文字之一:如果 x 在列表中,我 return 它;否则我 return 后备值:

from typing import Literal, Set

Foo = Literal[0, 1, 2]
foos: Set[Foo] = {0, 1, 2}
 
def convert_to_foo(x: int) -> Foo:
  if x in foos:
    # x must have type Foo, yet this doesn't type check
    y: Foo = x
    return y
  return 0

不幸的是,这没有类型检查。 Mypy returns 以下消息(参见 gist):

main.py:9: error: Incompatible types in assignment (expression has type "int", variable has type "Union[Literal[0], Literal[1], Literal[2]]")

如果我属于 Foo 的列表,那么我就是 Foo,对吗?我在文档中找不到答案,有人可以指出正确的方向吗?

我已经在 windows Python3.8 上测试了你的代码,没有发现任何问题。

from typing import Literal, Set

Foo = Literal[0, 1, 2]
foos: Set[Foo] = {0, 1, 2}

def convert_to_foo(x: int) -> Foo:
    if x in foos:
        # x must have type Foo, yet this doesn't type check
        y: Foo = x
        print(y)
        return y
    return 0

>>> convert_to_foo(3)
0
>>> convert_to_foo(2)
2
2

你到底想做什么?在这里它检查是否对于 3 和 returns 0 对于 2 returns 2。 这不是你检查的吗?

我试过了x:Any, default: int

from typing import Literal, Set
from typing import *

Foo = Literal[0, 1, 2]
foos: Set[Foo] = {0, 1, 2}

def convert_to_foo(x:Any, default: int) -> Foo:
  if x in foos:
    # x must have type Foo, yet this doesn't type check
    y: Foo = x
    return y
  return 0

成功:在 1 个源文件中未发现问题

问得好。我 认为 cast 可能是去这里的唯一途径:

from typing import Literal, Set, cast

Foo = Literal[0, 1, 2]
foos: Set[Foo] = {0, 1, 2}
 
def convert_to_foo(x: int) -> Foo:
    if x in foos:
        y: Foo = cast(Foo, x)
        return y
    return 0