在Python中动态定义Literal字符串排列的并集



我有一个字符串列表:

strings = ['a','b','c']

我想声明列表中所有可能的有序对的Literal类型的Union。硬编码,这看起来像:

CustomType = Literal[
'ab', 'ac', 'aa',
'ba', 'bb', 'bc',
'ca', 'cb', 'cc'
]

如何动态定义CustomType,这样就不必手动放置每个组合?

我想的是:

CustomType = Literal[*permutations(strings)]

但这给了我一个错误:

Unpack operator in subscript requires Python 3.11 or newer 
Pylance
Unpacked arguments cannot be used in type argument lists 
Pylance

激发这个问题的目的是让Pylance检测我是否尝试传递一个不是该集合元素的字符串。

def f(string: CustomType):
...
f('foo') # Pylance will complain
f('ba') # Pylance will permit
根据mypy文档的说法,您正在寻找的确切方法在Python中还不可能实现。官方代码与一些类似的问题相互作用,答案只是写出每一个排列,就像核心团队打字时的官方存根一样

然而,您可以使用类似Sequence:的东西来接近

CustomType = Sequence[Literal['a', 'b', 'c']]
func(('a', 'b', 'c'))
func(('d', 'e'))  # fails
func(('a',))
func(['a', 'b'])

遗憾的是,您仍然不能使用字符串作为参数:

func('abc')  # fails — sequence of strings, not literals
func(tuple('abc'))  # fails — tuple derived from a string becomes sequence of strings, not the needed CustomFlags.
arg: CustomType = 'ab'  # fails, the str can't be assigned out.

如果正好需要两个元素,请使用Tuple:

CustomOption = Literal['a', 'b', 'c']
CustomType = Tuple[CustomOption, CustomOption]
func(('a', 'b'))
func(('a', 'b', 'c'))  # fails

Literal接受元组的动态输入,您可以使用itertools生成所有组合:

from typing import Literal
from itertools import product
strings='abc'
Literal[tuple(x+y for x,y in product(strings, repeat=2))]

输出typing.Literal['aa', 'ab', 'ac', 'ba', 'bb', 'bc', 'ca', 'cb', 'cc']

与pydantic核对

from pydantic import BaseModel

class NewClass(BaseModel):
string: Literal[tuple(x + y for x, y in product("abc", repeat=2))]

NewClass(string="aa")

相关内容

  • 没有找到相关文章

最新更新