foo
假设我有一个包含例如元素的数组[1, 2, 3]
,并且我想检索foo
好像foo
已“无限连接”的元素。
例如foo[0:2]
将返回(如普通列表):
[1, 2]
并foo[0:5]
会返回:
[1, 2, 3, 1, 2]
而foo[7:13]
会返回:
[2, 3, 1, 2, 3, 1]
Python 中是否有任何数据容器或扩展模块已经促进了这种类型的访问?如果不是,那么提供这个容器的好/简单的方法是什么?
foo
假设我有一个包含例如元素的数组[1, 2, 3]
,并且我想检索foo
好像foo
已“无限连接”的元素。
例如foo[0:2]
将返回(如普通列表):
[1, 2]
并foo[0:5]
会返回:
[1, 2, 3, 1, 2]
而foo[7:13]
会返回:
[2, 3, 1, 2, 3, 1]
Python 中是否有任何数据容器或扩展模块已经促进了这种类型的访问?如果不是,那么提供这个容器的好/简单的方法是什么?
恐怕您必须自己实施。不过这并不难:
class cyclist(list):
def __getitem__(self, index):
return list.__getitem__(self, index % len(self))
def __getslice__(self, start, stop):
return [self[n] for n in range(start, stop)]
foo = cyclist([1, 2, 3])
print foo[0:2] # [1, 2]
print foo[7:13] # [2, 3, 1, 2, 3, 1]
print foo[0:5] # [1, 2, 3, 1, 2]
它缺少一些细节,例如处理省略的切片参数、切片中的负数和切片步骤。
在处理看起来像列表但行为本质上不同的序列时,您应该小心。我建议使用 Pavel Anossov 的酷实现,但提供指定的get_cyclic_item
and
get_cyclic_slice
,而不是覆盖列表的__getitem__
and __getslice__
。
该类的用户可以轻松地对他正在使用的列表的行为做出假设(期望 ISA 关系,如“cyclicallist IS A list”),这将导致错误/错误。
cyclicallist
如果调用者不知道他使用的是 a而不是常规列表,以下是使用列表可能会令人困惑的情况的一些示例...
a = cyclicallist([ 0, 1, 2 ])
# appending a value at the end changes an "existing" index
print a[100]
a.append(99)
print a[100]
# deleting a value changes an index preceding it
print a[100]
del a[999] # currently gives an error: IndexError: list assignment index out of range
print a[100] # even if no error, what should this print?
# hmm...
del a[100:99999]
当然,空的语义cyclicallist
没有明确定义......
即使与上面建议的基于模的实现相比效率低得离谱,我认为使用它itertools
可能是一种有趣的方式......</p>
>>> from itertools import islice, cycle
>>> make_cyclic = lambda lst: lambda start, stop: list( islice( cycle( lst ), start, stop ) )
>>> make_cyclic( [ 1, 2, 3 ] )
>>> c(7, 13)
[2, 3, 1, 2, 3, 1]