描述枚举名称的字符串文字联合的类型表达式?

hur*_*lad 10 python enums python-typing

鉴于:

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3
Run Code Online (Sandbox Code Playgroud)

Foo是否存在这样的类型表达式:

Foo[Color] = Literal["RED", "GREEN", "BLUE"]
Run Code Online (Sandbox Code Playgroud)

bad*_*der 7

来自 PEP 586——文字类型

类型检查时文字的合法参数

Literal[Color.RED] # 假设 Color 是一些枚举

PEP 586 中还有:

文字、枚举和前向引用

  • Literal["Color.RED"](...) 在这样的情况下,我们总是假设用户想要构造一个文字字符串。
  • "Literal[Color.RED]"(...) 如果用户想要前向引用,他们必须将整个文字类型包装在字符串中
from typing import Literal
from enum import Enum


class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3


FIRST = Literal["RED", "GREEN", "BLUE"]
SECOND = Literal[Color.RED, Color.GREEN]
THIRD = Literal["Color.RED", "Color.GREEN"]


def one(arg: FIRST):
    print("FIRST")


def two(arg: SECOND):
    print("SECOND")


def three(arg: THIRD):
    print("THIRD")


one("GREEN")  # Linter issues no warning
one(Color.RED)  # Expected type 'Literal["RED", "GREEN", "BLUE"]', got 'Color' instead
one(Color.RED.name)  # Expected type 'Literal["RED", "GREEN", "BLUE"]', got 'str' instead 

two("RED")  # Expected type 'Color', got 'str' instead 
two(Color.RED)  # Linter issues no warning

three("RED")  # Expected type 'Literal["Color.RED", "Color.GREEN"]', got 'Literal["RED"]' instead 
three("Color.RED") # Linter issues no warning
three(Color.RED.name)  # Expected type 'Literal["Color.RED", "Color.GREEN"]', got 'str' instead 

Run Code Online (Sandbox Code Playgroud)

如果您想通过Literal传递枚举成员的集合作为参数来声明,我认为这是不可能的(请参阅:类型检查时文字的非法参数),静态类型检查器会给出以下警告:

“Literal”可以使用文字 int、字节和 unicode 字符串、布尔值、枚举值、None、其他文字类型或其他文字类型的类型别名进行参数化

此处不能使用加星号的表达式

teste_one = ("RED", "GREEN", "BLUE")
FIRST = Literal[teste_one]
FIRST = Literal[*teste_one]

test_two = Color.__members__.keys()
SECOND = Literal[test_two]
SECOND = Literal[*test_two]
Run Code Online (Sandbox Code Playgroud)

您始终必须显Literal[...]式声明参数。


Che*_*ops -2

您可以使用枚举名称编程访问来获得类似的效果,例如:

class Colors(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3
   

ColorsNames = [color.name for color in Colors]

print(ColorsNames)

['RED', 'GREEN', 'BLUE']
Run Code Online (Sandbox Code Playgroud)

  • 但这对于静态类型来说毫无用处。 (5认同)