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

Python Tuple-Enum无法使用第二个元素为0的元组的问题求助

问题

我想在国际象棋程序中用继承tuple的Enum类作为棋盘坐标,代码如下:

from enum import Enum
class Pos(tuple, Enum):
    A1 = (0, 0)
    A2 = (0, 1)
    B1 = (1, 0)
    B2 = (1, 1)

但所有第二个元素为0的坐标都会触发ValueError,比如执行:

print(Pos(1, 0))

报错信息:

Traceback (most recent call last):
  File "C:\Users\TuffGolem\AppData\Roaming\JetBrains\PyCharmCE2023.3\scratches\scratch_6.py", line 11, in <module>
    print(Pos(1, 0))
          ^^^^^^^^^
  File "C:\Users\TuffGolem\AppData\Local\Programs\Python\Python312\Lib\enum.py", line 740, in __call__
    return cls.__new__(cls, value)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\TuffGolem\AppData\Local\Programs\Python\Python312\Lib\enum.py", line 1154, in __new__
    raise ve_exc
ValueError: 1 is not a valid Pos

看起来程序忽略了第二个元素0,只拿第一个数字去匹配枚举值。我之前给每个坐标值加1规避,但这只是临时方案,而且因为要把元组作为Numpy数组的坐标,这个方法行不通。请问怎么正常使用第二个元素为0的坐标?

解决方案

问题根源在于Enum的构造逻辑:当继承tuple并调用Pos(1, 0)时,Python会将多个参数当作tuple的构造参数,而Enum的__call__方法会优先用第一个参数匹配枚举成员,而非将所有参数打包成完整元组匹配。

方法一:显式传入元组(Ethan Furmann方案)

给坐标元组添加额外括号,明确告诉Enum要匹配的是完整元组对象:

print(Pos((1, 0)))  # 输出 Pos.B1

这种方式能让Enum正确识别你要匹配的是完整的元组值,而非拆分后的单个参数。

方法二:重写__call__方法简化调用

如果想保留Pos(1,0)的直观调用方式,可以重写Enum的__call__方法,强制将多参数打包成元组:

from enum import Enum
class Pos(tuple, Enum):
    A1 = (0, 0)
    A2 = (0, 1)
    B1 = (1, 0)
    B2 = (1, 1)
    
    def __call__(cls, *args):
        if len(args) > 1:
            return cls(tuple(args))
        return super().__call__(*args)

修改后直接调用Pos(1,0)就能正确返回Pos.B1,同时也兼容Pos((1,0))的调用方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 03:52:29