<p>这里有一个基于pypy库代码的解决方案(感谢agf在评论中的建议)。在</p>
<p>状态通过<code>.state</code>属性可用,并且可以通过<code>.goto(state)</code>重置,其中<code>state</code>是序列的索引(从0开始)。最后有一个演示(恐怕你需要向下滚动)。在</p>
<p>这比丢弃值快得多。在</p>
<pre><code>> cat prod.py
class product(object):
def __init__(self, *args, **kw):
if len(kw) > 1:
raise TypeError("product() takes at most 1 argument (%d given)" %
len(kw))
self.repeat = kw.get('repeat', 1)
self.gears = [x for x in args] * self.repeat
self.num_gears = len(self.gears)
self.reset()
def reset(self):
# initialization of indicies to loop over
self.indicies = [(0, len(self.gears[x]))
for x in range(0, self.num_gears)]
self.cont = True
self.state = 0
def goto(self, n):
self.reset()
self.state = n
x = self.num_gears
while n > 0 and x > 0:
x -= 1
n, m = divmod(n, len(self.gears[x]))
self.indicies[x] = (m, self.indicies[x][1])
if n > 0:
self.reset()
raise ValueError("state exceeded")
def roll_gears(self):
# Starting from the end of the gear indicies work to the front
# incrementing the gear until the limit is reached. When the limit
# is reached carry operation to the next gear
self.state += 1
should_carry = True
for n in range(0, self.num_gears):
nth_gear = self.num_gears - n - 1
if should_carry:
count, lim = self.indicies[nth_gear]
count += 1
if count == lim and nth_gear == 0:
self.cont = False
if count == lim:
should_carry = True
count = 0
else:
should_carry = False
self.indicies[nth_gear] = (count, lim)
else:
break
def __iter__(self):
return self
def next(self):
if not self.cont:
raise StopIteration
l = []
for x in range(0, self.num_gears):
index, limit = self.indicies[x]
l.append(self.gears[x][index])
self.roll_gears()
return tuple(l)
p = product('abc', '12')
print list(p)
p.reset()
print list(p)
p.goto(2)
print list(p)
p.goto(4)
print list(p)
> python prod.py
[('a', '1'), ('a', '2'), ('b', '1'), ('b', '2'), ('c', '1'), ('c', '2')]
[('a', '1'), ('a', '2'), ('b', '1'), ('b', '2'), ('c', '1'), ('c', '2')]
[('b', '1'), ('b', '2'), ('c', '1'), ('c', '2')]
[('c', '1'), ('c', '2')]
</code></pre>
<p>你应该对它进行更多的测试——我可能犯了一个愚蠢的错误——但是这个想法很简单,所以你应该能够修复它:o)你可以自由使用我的更改;不知道原始的pypy许可是什么。在</p>
<p>而且<code>state</code>不是真正的完整状态-它不包括原始参数-它只是序列的一个索引。也许把它称为索引会更好,但代码中已经有了标记。。。在</p>
<p><strong>更新</strong></p>
<p>这里有一个更简单的版本,它的想法是一样的,但是通过转换一系列的数字来工作。所以你只要<code>imap</code>在<code>count(n)</code>上,就可以得到<code>n</code>的序列偏移量。在</p>
^{pr2}$
<p>(这里的缺点是,如果您想停止并重新启动,您需要跟踪自己已经使用了多少次)</p>