Python中的子类元组来模拟无限重复序列?

问题描述 投票:0回答:1

我有一个由 16 个元素组成的序列(具体来说,是庄家和桥板的漏洞),理论上它们会无限重复(实际上,它几乎永远不会超过 128 个,很少超过 36 个)。

即17、33、49、65、...板上的信息与1板相同。(按理说,没有0板,但假装是16板我很高兴,也)。

我想创建一个类似元组的对象,它将返回任意索引的正确信息:例如 board_info[129]。 如果我能像普通元组那样对它进行切片,那就太好了:board_info[15:22] 为从 15 开始的 7 个板获取 len-7 元组。

我知道我可以创建一个函数来为一块板做正确的事情,例如:

# BoardInfo is the object containing board-specific information
# instantiate DEALVUL as "BoardInfo for boards 0-15" here

def board_info(board: int) -> BoardInfo:
    return DEALVUL[board % 16]

但是一些“原生”的东西允许我将其视为具有元组所有功能的不可变序列(切片,获取下一个,...)会更有用。

我尝试过类似的方法(注意,我知道这行不通)

class BInfo(tuple):
    """Infinite list of board information."""

    def __new__(cls):
        return tuple.__new__(*DEALVUL)

    def __getitem__(self, board_number: int) -> BoardInfo:
        return self[board_number % 16]

    def __iter__(self):
        return iter(self)

    def __next__(self):
        try:
            return next(self)
        except StopIteration:
           # reset the iterator to zero and
            return next(self) 

很明显我不懂魔法方法。

python-3.x sequence subclassing
1个回答
0
投票

您可以创建一个可切片视图,该视图在给定序列的

itertools.islice
上返回
itertools.cycle
,该序列直接从给定起始索引的序列大小模数开始:

from itertools import cycle, islice

class CycleView:
    def __init__(self, seq):
        self.seq = seq

    def __getitem__(self, index):
        if isinstance(index, slice):
            start = (index.start or 0) % len(self.seq)
            if (stop := index.stop) is not None:
                stop = start + stop - (index.start or 0)
            return islice(cycle(self.seq), start, stop)
        return self.seq[index]

举个例子:

DEADVUL = 'x', 'y', 'z'
print(*CycleView(DEADVUL)[:10])
print(*CycleView(DEADVUL)[2000000000:2000000010])

输出:

x y z x y z x y z x
z x y z x y z x y z

演示:https://ideone.com/UJGwiP

© www.soinside.com 2019 - 2024. All rights reserved.