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

如何在Python中通过子类化tuple实现无限重复序列?

解决无限循环桥牌局况序列的实现问题

原代码的问题分析

  • 继承tuple的误区:tuple是不可变序列,其内部实现依赖固定长度数组,继承后自定义的__getitem__不会覆盖原生行为,实例化后本质仍是普通tuple。
  • __new__方法调用错误:tuple.__new__(*DEALVUL)参数格式错误,正确写法应为tuple.__new__(cls, DEALVUL),但即使修正,生成的仍是普通tuple,无法使用自定义逻辑。
  • 无限递归问题:__getitem__中self[board_number % 16]会递归调用自身,导致栈溢出。
  • 迭代器实现错误:__iter__返回iter(self)会使用tuple的有限迭代器,__next__定义在序列类上不符合迭代器协议,无法实现无限循环迭代。

正确实现方案:基于Sequence抽象基类

通过实现collections.abc.Sequence抽象基类,可快速获得序列核心特性(切片、in操作、count/index方法等),同时自定义循环逻辑:

from collections.abc import Sequence

class BoardInfo:
    """示例:存储桥牌局况信息的类"""
    def __init__(self, board_id, dealer, vulnerability):
        self.board_id = board_id
        self.dealer = dealer
        self.vulnerability = vulnerability

    def __repr__(self):
        return f"BoardInfo(board={self.board_id}, dealer={self.dealer}, vul={self.vulnerability})"

# 初始化基础序列:对应0-15副牌的局况
DEALVUL = [
    BoardInfo(0, 'N', 'None'),
    BoardInfo(1, 'E', 'NS'),
    BoardInfo(2, 'S', 'EW'),
    BoardInfo(3, 'W', 'Both'),
    BoardInfo(4, 'N', 'NS'),
    BoardInfo(5, 'E', 'EW'),
    BoardInfo(6, 'S', 'Both'),
    BoardInfo(7, 'W', 'None'),
    BoardInfo(8, 'N', 'EW'),
    BoardInfo(9, 'E', 'Both'),
    BoardInfo(10, 'S', 'None'),
    BoardInfo(11, 'W', 'NS'),
    BoardInfo(12, 'N', 'Both'),
    BoardInfo(13, 'E', 'None'),
    BoardInfo(14, 'S', 'NS'),
    BoardInfo(15, 'W', 'EW'),
]

class BoardInfoSequence(Sequence):
    """无限循环的桥牌局况序列,兼容tuple核心特性"""
    def __init__(self, base_seq):
        self.base = base_seq
        self.cycle_len = len(base_seq)
        if self.cycle_len == 0:
            raise ValueError("Base sequence cannot be empty")

    def __getitem__(self, key):
        if isinstance(key, int):
            # 处理整数索引,支持正负索引
            idx = key % self.cycle_len
            return self.base[idx]
        elif isinstance(key, slice):
            # 处理切片,生成对应长度的不可变tuple
            # 用float('inf')作为切片的默认终止位置,适配无限序列
            start, stop, step = key.indices(float('inf'))
            result = []
            current = start
            while current < stop:
                result.append(self[current])
                current += step if step is not None else 1
            return tuple(result)
        else:
            raise TypeError(f"Invalid index type: {type(key).__name__}")

    def __len__(self):
        # 返回足够大的数值适配实际使用场景(用户提到很少超过36次)
        return 128

    def __iter__(self):
        # 实现无限循环迭代器
        while True:
            yield from self.base

# 实例化序列
board_info = BoardInfoSequence(DEALVUL)

使用示例

  1. 访问任意索引:
# 第17副牌(对应第1副)
print(board_info[16])  # 输出: BoardInfo(board=0, dealer=N, vul=None)
print(board_info[17])  # 输出: BoardInfo(board=1, dealer=E, vul=NS)
# 第129副牌:129 % 16 = 1 → 对应第1副
print(board_info[129]) # 输出: BoardInfo(board=1, dealer=E, vul=NS)
  1. 切片操作:
# 获取第15到22副牌(共7副)
slice_result = board_info[15:22]
print(slice_result)
# 输出: (
#   BoardInfo(board=15, dealer=W, vul=EW),
#   BoardInfo(board=0, dealer=N, vul=None),
#   BoardInfo(board=1, dealer=E, vul=NS),
#   BoardInfo(board=2, dealer=S, vul=EW),
#   BoardInfo(board=3, dealer=W, vul=Both),
#   BoardInfo(board=4, dealer=N, vul=NS),
#   BoardInfo(board=5, dealer=E, vul=EW)
# )
  1. 无限迭代:
from itertools import islice

# 迭代前20副牌
for board in islice(board_info, 0, 20):
    print(board.board_id)
# 输出: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1 2 3

关键特性说明

  • 不可变性:切片返回tuple,保证序列的不可变特性,符合用户对tuple特性的需求。
  • 兼容性:继承Sequence后自动支持in、count()、index()等序列方法。
  • 性能:基础序列仅存储一次,所有索引/切片操作均基于模运算获取元素,内存占用低。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:57:14