如何解决修改Literal类型属性时出现的mypy错误?
问题
需要修改Literal类型的属性值,实际场景中ValidChar包含大量取值,需转换为List[str]做校验,但示例代码运行时mypy报错。
原代码:
from typing import Literal ValidChar = Literal["A", "B"] class MyClass: char: ValidChar = "A" def set_char(self, char: str) -> None: """Set only valid character.""" if char in ValidChar.__args__: self.char = char obj = MyClass() print(f"{obj.char=}") # obj.char='A' # 合法字符 obj.set_char("B") print(f"{obj.char=}") # obj.char='B' # 非法字符 obj.set_char("C") print(f"{obj.char=}") # obj.char='B'
mypy报错信息
$ mypy . 2.py:11: error: "<typing special form>" has no attribute "__args__" [attr-defined] 2.py:12: error: Incompatible types in assignment (expression has type "str", variable has type "Literal['A', 'B']") [assignment] Found 2 errors in 1 file (checked 3 source files)
解决方案
方法一:先维护有效值列表,再生成Literal类型
先定义真实的有效值列表,基于列表生成Literal类型,既满足运行时校验需求,又能保留静态类型检查,还避免依赖内部属性:
from typing import Literal, cast # 维护真实的有效值列表,后续只需修改这里即可 VALID_CHARS = ["A", "B"] # 基于列表生成Literal类型 ValidChar = Literal[tuple(VALID_CHARS)] class MyClass: char: ValidChar = "A" def set_char(self, char: str) -> None: """Set only valid character.""" if char in VALID_CHARS: # 使用cast明确告诉mypy当前char符合ValidChar类型 self.char = cast(ValidChar, char)
方法二:用typing.get_args获取Literal参数(Python 3.8+)
如果不想额外维护列表,可使用官方提供的get_args方法获取Literal的参数,mypy认可该方法:
from typing import Literal, get_args, cast ValidChar = Literal["A", "B"] class MyClass: char: ValidChar = "A" def set_char(self, char: str) -> None: """Set only valid character.""" if char in get_args(ValidChar): # 用cast解决类型赋值不兼容问题 self.char = cast(ValidChar, char)
补充说明
- 若觉得
cast麻烦,也可以用类型忽略注释# type: ignore[assignment]替代,但要注意后续修改ValidChar时需同步校验逻辑,避免类型风险。 - 如果调用方也能保证传入参数的类型,可直接将
set_char的参数类型改为ValidChar,无需额外校验,但这种方式无法直接接收str类型参数。
内容的提问来源于stack exchange,提问作者pyjedy
相关产品推荐
相关产品推荐

