You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pyright报错tuple[str, str]无法匹配Literal元组键,代码却能运行?

问题原因与解决办法

问题根源

Pyright是静态类型检查工具,它无法推断出你从文件读取并通过split()得到的u和v严格限定在A/B/C和X/Y/Z这些特定字符串中,因此会将它们的类型判定为普通str。而你的score_table字典的键被Pyright识别为由具体字面量组成的元组(例如tuple[Literal['A'], Literal['X']]这类精确类型),普通str组成的tuple[str, str]与这些字面量元组类型不兼容,于是抛出类型错误。

但实际运行时,输入文件day2.in的内容确实都是符合要求的字符组合,所以代码能正常执行并得到正确结果——静态检查的错误仅源于类型系统无法确认输入的实际值范围。

解决办法

以下几种方式可以让Pyright认可类型匹配:

1. 给变量添加字面量类型标注

使用typing.Literal明确指定u和v的可能取值:

from typing import Literal

if __name__ == "__main__":
    with open("day2.in", "r", encoding="utf-8") as f:
        score = {'X': 1, 'Y': 2, 'Z': 3}
        score_table = {('A', 'X'): 3, ('A', 'Y'): 6, ('A', 'Z'): 0,
                       ('B', 'X'): 0, ('B', 'Y'): 3, ('B', 'Z'): 6,
                       ('C', 'X'): 6, ('C', 'Y'): 0, ('C', 'Z'): 3}
        ans = 0
        for line in f:
            u, v = line.split()
            # 明确标注取值范围,告知Pyright类型信息
            u: Literal['A', 'B', 'C'] = u
            v: Literal['X', 'Y', 'Z'] = v
            ans += score[v] + score_table[(u, v)]

        print(ans)

2. 使用类型断言

若你能确保输入不会出现非法值,可通过类型断言强制告知Pyright元组的类型:

for line in f:
    u, v = line.split()
    # 断言元组类型匹配score_table的键类型
    key = (u, v)  # type: tuple[Literal['A','B','C'], Literal['X','Y','Z']]
    ans += score[v] + score_table[key]

3. 用枚举类替代字面量(更规范的方案)

使用枚举类定义合法取值,既消除类型错误,又提升代码可读性,还能在输入非法值时快速报错:

from enum import Enum

class OpponentChoice(Enum):
    ROCK = 'A'
    PAPER = 'B'
    SCISSORS = 'C'

class MyChoice(Enum):
    ROCK = 'X'
    PAPER = 'Y'
    SCISSORS = 'Z'

if __name__ == "__main__":
    with open("day2.in", "r", encoding="utf-8") as f:
        score = {MyChoice.ROCK: 1, MyChoice.PAPER: 2, MyChoice.SCISSORS: 3}
        score_table = {
            (OpponentChoice.ROCK, MyChoice.ROCK): 3,
            (OpponentChoice.ROCK, MyChoice.PAPER): 6,
            (OpponentChoice.ROCK, MyChoice.SCISSORS): 0,
            (OpponentChoice.PAPER, MyChoice.ROCK): 0,
            (OpponentChoice.PAPER, MyChoice.PAPER): 3,
            (OpponentChoice.PAPER, MyChoice.SCISSORS): 6,
            (OpponentChoice.SCISSORS, MyChoice.ROCK): 6,
            (OpponentChoice.SCISSORS, MyChoice.PAPER): 0,
            (OpponentChoice.SCISSORS, MyChoice.SCISSORS): 3,
        }
        ans = 0
        for line in f:
            u_str, v_str = line.split()
            u = OpponentChoice(u_str)
            v = MyChoice(v_str)
            ans += score[v] + score_table[(u, v)]

        print(ans)

内容的提问来源于stack exchange,提问作者Harry Zhou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 03:43:18