Python3.x移动范围
假设我有这样一个范围:Python3.x移动范围,python,loops,python-3.x,range,Python,Loops,Python 3.x,Range,假设我有这样一个范围: x = range(10) 将具有以下值作为列表: list(x) # Prints [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 我想改变这个范围(可能多次) 并对结果进行迭代,例如 # [7, 8, 9, 0, 1, 2, 3, 4, 5, 6] 创建等效列表不是问题。但是我想 知道是否有可能创造出这样的东西 一个范围可以在内存中节省一些空间,当然它会 如果解决方案的性能可以达到: for i i
x = range(10)
将具有以下值作为列表:
list(x) # Prints [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
我想改变这个范围(可能多次)
并对结果进行迭代,例如
# [7, 8, 9, 0, 1, 2, 3, 4, 5, 6]
创建等效列表不是问题。但是我想
知道是否有可能创造出这样的东西
一个范围可以在内存中节省一些空间,当然它会
如果解决方案的性能可以达到:
for i in range(1000000)
可以在生成器表达式中包装范围,动态应用移位和模:
def shifted_range(rangeob, shift):
size, shift = rangeob.stop, shift * rangeob.step
return ((i + shift) % size for i in rangeob)
演示:
您还可以将其作为包装器对象:
class RangeShift:
def __init__(self, rangeob, shift):
self._range = rangeob
self.shift = shift
@property
def start(self):
r = self._range
return (r.start + self.shift * r.step) % r.stop
@property
def stop(self):
r = self._range
return (r.stop + self.shift * r.step) % r.stop
def index(self, value):
idx = self._range.index(value)
return (idx - self.shift) % len(self._range)
def __getattr__(self, attr):
return getattr(self._range, attr)
def __getitem__(self, index):
r = self._range
return (r[index] + self.shift * r.step) % r.stop
def __len__(self):
return len(self._range)
def __iter__(self):
size, shift = self._range.stop, self.shift * self._range.step
return ((i + shift) % size for i in self._range)
这将与原始范围一样,但会对生成的所有值应用移位。它甚至可以让你改变班次
演示:
此包装器现在支持的最佳技巧:反转移位范围:
>>> list(reversed(shifted))
[2, 1, 0, 9, 8, 7, 6, 5, 4, 3]
>>> list(reversed(shifted_10_2))
[6, 4, 2, 0, 8]
我想最简单的方法是将其分为两个范围:
from itertools import chain
shifted = chain(range(7, 10), range(7))
for x in shifted:
print(x)
您可以使用itertools链接两个范围。即使范围的步长大于1,此代码也有效
import itertools
def shift_range(r, s):
return itertools.chain(range(r.start + s*r.step, r.stop, r.step),
range(r.start, r.start + s*r.step, r.step))
测试:
>>> list(shift_range(range(10), 5))
[5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
>>> list(shift_range(range(3, 30, 3), 5))
[18, 21, 24, 27, 3, 6, 9, 12, 15]
谢谢你的详细回答。(我猜至少有一条包含感谢的评论是被允许的,不会被视为垃圾邮件):P
import itertools
def shift_range(r, s):
return itertools.chain(range(r.start + s*r.step, r.stop, r.step),
range(r.start, r.start + s*r.step, r.step))
>>> list(shift_range(range(10), 5))
[5, 6, 7, 8, 9, 0, 1, 2, 3, 4]
>>> list(shift_range(range(3, 30, 3), 5))
[18, 21, 24, 27, 3, 6, 9, 12, 15]