我有一个由 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)
很明显我不懂魔法方法。
您可以创建一个可切片视图,该视图在给定序列的
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