首页 > 解决方案 > 类型表达式描述枚举名称的字符串文字联合?

问题描述

鉴于:

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

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

Foo[Color] = Literal["RED", "GREEN", "BLUE"]

标签: pythonenumstyping

解决方案


来自 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 

如果您想Literal通过将枚举成员的集合作为参数传递来声明,我认为这是不可能的(请参阅:Illegal parameters for Literal at type check time),静态类型检查器会发出以下警告:

'Literal' 可以用字面量整数、字节和 Unicode 字符串、布尔值、枚举值、无、其他字面量类型或其他字面量类型的类型别名参数化

此处不能使用星号表达

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]

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


推荐阅读