复制一个 itertools 循环对象
Copy an itertools cycle object
我想制作一个 itertools.cycle
对象的浅表副本,但我不知道怎么做,因为它没有内置的复制方法。我想实现如下所示,我创建循环的副本,迭代几次,然后再次复制原始副本,再迭代几次从循环的开头开始.
c = "ABCD"
cyc = itertools.cycle(c)
cyc_copy = cyc.copy()
for i in range(2):
print(next(cyc_copy))
cyc_copy = cyc.copy()
for i in range(2):
print(next(cyc_copy))
> A
B
A
B
copy
应该可以解决问题:
>>> from copy import copy
>>> cyc_copy = copy(cyc)
>>> next(cyc_copy)
'A'
>>> next(cyc_copy)
'B'
>>> cyc_copy = copy(cyc)
>>> next(cyc_copy)
'A'
>>> next(cyc_copy)
'B'
复制循环本身会 运行 出问题。例如,copy.copy
ing it doesn't produce independent copies.
与其尝试复制循环,我建议从您的原始对象重新创建它:
new_cyc = itertools.cycle(c)
如果您创建原始循环的对象是一个迭代器,您不能只是重复调用 cycle
。相反,在第一次调用 cycle
之前列一个列表,并保留列表:
c_list = list(c)
cyc = itertools.cycle(c_list)
# later
new_cyc = itertools.cycle(c_list)
如果您创建原始循环的对象是一个可能无限也可能不是无限的迭代器,您不能安全地对其调用 list
。相反,您可以 tee
在 创建循环之前 和 copy.copy
在需要创建新循环时使用不高级的发球台。 (tee
支持复制。)
c_tee, c_tee2 = itertools.tee(c)
cyc = itertools.cycle(c_tee2)
# Copy c_tee, not the c_tee2 we already used.
new_cyc = itertools.cycle(copy.copy(c_tee))
所有这些都假定您控制循环的创建。如果您从其他地方接收到一个循环,您可能无法访问它循环过的对象。在这种情况下,您最好的选择是 tee
循环本身。如果您需要经历循环的许多循环,这可能会很昂贵:
cyc_master, cyc1 = itertools.tee(cyc)
# Use cyc1
# Later
cyc2 = copy.copy(cyc_master)
您可以创建自定义 class 来执行您想要的操作:
import itertools
class CopyCycle:
def __init__(self, iterable):
self.iterable = iterable
self._cycle = itertools.cycle(self.iterable)
def cycle(self):
return self
def __iter__(self):
return self
def next(self):
return self._cycle.next()
def __next__(self): #Python 3+
return self._cycle.next()
def copy(self):
return CopyCycle(self.iterable)
if __name__ == '__main__':
cyc = CopyCycle("ABCD").cycle()
for i in range(5):
print(next(cyc))
cyc_copy = cyc.copy()
for i in range(2):
print(next(cyc_copy))
cyc_copy = cyc.copy()
for i in range(2):
print(next(cyc_copy))
输出:
A
B
C
D
A
A
B
A
B
它可能需要一些重构,但工厂在这里会工作得很好。
from itertools import cycle
cycle_factory = lambda: cycle('1234')
c1 = cycle_factory()
print next(c1) # 1
c2 = cycle_factory()
print next(c2) # 1
否则,我不确定你是否能够满足每次都在循环开始时开始的标准。基于 class 的方法也可以工作,但需要更多的开销。
itertools.tee
方法的一个问题是它会在 tee-d 迭代器停止的地方恢复迭代,而不是从头开始。因此,您必须在一开始就开球。如果您无法控制循环的生成方式,这可能是唯一的选择。
方法一:制作两个itertools.cycle
对象
import itertools
c = 'ABCD'
cyc1 = itertools.cycle(c)
cyc2 = itertools.cycle(c)
for _ in range(2): print(next(cyc1)) # prints A\nB\n
for _ in range(2): print(next(cyc2)) # prints A\nB\n
<script src="//repl.it/embed/IRcx/0.js"></script>
[首选方案]方法二:使用itertools.tee
拆分为n个迭代器
import itertools
cyc = itertools.cycle('ABCD')
cyc1, cyc2 = itertools.tee(cyc, 2)
for _ in range(2): print(next(cyc1)) # prints A\nB\n
for _ in range(2): print(next(cyc2)) # prints A\nB\n
<script src="//repl.it/embed/IRcx/2.js"></script>
Warning using copy
module using the copy.copy
function 将不会按预期创建迭代器的副本。
import itertools, copy
cyc = itertools.cycle('ABCD')
cyc1 = copy.copy(cyc)
cyc2 = copy.copy(cyc)
for _ in range(2): print(next(cyc1)) # prints A\nB\n
for _ in range(2): print(next(cyc2)) # prints C\nD\n
<script src="//repl.it/embed/IRcx/3.js"></script>
使用 copy
模块的解决方法: 一个可能的解决方案是使用 copy.deepcopy
函数。
import itertools, copy
cyc = itertools.cycle('ABCD')
cyc1 = copy.deepcopy(cyc)
cyc2 = copy.deepcopy(cyc)
for _ in range(2): print(next(cyc1)) # prints A\nB\n
for _ in range(2): print(next(cyc2)) # prints A\nB\n
<script src="//repl.it/embed/IRcx/4.js"></script>
我想制作一个 itertools.cycle
对象的浅表副本,但我不知道怎么做,因为它没有内置的复制方法。我想实现如下所示,我创建循环的副本,迭代几次,然后再次复制原始副本,再迭代几次从循环的开头开始.
c = "ABCD"
cyc = itertools.cycle(c)
cyc_copy = cyc.copy()
for i in range(2):
print(next(cyc_copy))
cyc_copy = cyc.copy()
for i in range(2):
print(next(cyc_copy))
> A
B
A
B
copy
应该可以解决问题:
>>> from copy import copy
>>> cyc_copy = copy(cyc)
>>> next(cyc_copy)
'A'
>>> next(cyc_copy)
'B'
>>> cyc_copy = copy(cyc)
>>> next(cyc_copy)
'A'
>>> next(cyc_copy)
'B'
复制循环本身会 运行 出问题。例如,copy.copy
ing it doesn't produce independent copies.
与其尝试复制循环,我建议从您的原始对象重新创建它:
new_cyc = itertools.cycle(c)
如果您创建原始循环的对象是一个迭代器,您不能只是重复调用 cycle
。相反,在第一次调用 cycle
之前列一个列表,并保留列表:
c_list = list(c)
cyc = itertools.cycle(c_list)
# later
new_cyc = itertools.cycle(c_list)
如果您创建原始循环的对象是一个可能无限也可能不是无限的迭代器,您不能安全地对其调用 list
。相反,您可以 tee
在 创建循环之前 和 copy.copy
在需要创建新循环时使用不高级的发球台。 (tee
支持复制。)
c_tee, c_tee2 = itertools.tee(c)
cyc = itertools.cycle(c_tee2)
# Copy c_tee, not the c_tee2 we already used.
new_cyc = itertools.cycle(copy.copy(c_tee))
所有这些都假定您控制循环的创建。如果您从其他地方接收到一个循环,您可能无法访问它循环过的对象。在这种情况下,您最好的选择是 tee
循环本身。如果您需要经历循环的许多循环,这可能会很昂贵:
cyc_master, cyc1 = itertools.tee(cyc)
# Use cyc1
# Later
cyc2 = copy.copy(cyc_master)
您可以创建自定义 class 来执行您想要的操作:
import itertools
class CopyCycle:
def __init__(self, iterable):
self.iterable = iterable
self._cycle = itertools.cycle(self.iterable)
def cycle(self):
return self
def __iter__(self):
return self
def next(self):
return self._cycle.next()
def __next__(self): #Python 3+
return self._cycle.next()
def copy(self):
return CopyCycle(self.iterable)
if __name__ == '__main__':
cyc = CopyCycle("ABCD").cycle()
for i in range(5):
print(next(cyc))
cyc_copy = cyc.copy()
for i in range(2):
print(next(cyc_copy))
cyc_copy = cyc.copy()
for i in range(2):
print(next(cyc_copy))
输出:
A B C D A A B A B
它可能需要一些重构,但工厂在这里会工作得很好。
from itertools import cycle
cycle_factory = lambda: cycle('1234')
c1 = cycle_factory()
print next(c1) # 1
c2 = cycle_factory()
print next(c2) # 1
否则,我不确定你是否能够满足每次都在循环开始时开始的标准。基于 class 的方法也可以工作,但需要更多的开销。
itertools.tee
方法的一个问题是它会在 tee-d 迭代器停止的地方恢复迭代,而不是从头开始。因此,您必须在一开始就开球。如果您无法控制循环的生成方式,这可能是唯一的选择。
方法一:制作两个itertools.cycle
对象
import itertools
c = 'ABCD'
cyc1 = itertools.cycle(c)
cyc2 = itertools.cycle(c)
for _ in range(2): print(next(cyc1)) # prints A\nB\n
for _ in range(2): print(next(cyc2)) # prints A\nB\n
<script src="//repl.it/embed/IRcx/0.js"></script>
[首选方案]方法二:使用itertools.tee
import itertools
cyc = itertools.cycle('ABCD')
cyc1, cyc2 = itertools.tee(cyc, 2)
for _ in range(2): print(next(cyc1)) # prints A\nB\n
for _ in range(2): print(next(cyc2)) # prints A\nB\n
<script src="//repl.it/embed/IRcx/2.js"></script>
Warning using copy
module using the copy.copy
function 将不会按预期创建迭代器的副本。
import itertools, copy
cyc = itertools.cycle('ABCD')
cyc1 = copy.copy(cyc)
cyc2 = copy.copy(cyc)
for _ in range(2): print(next(cyc1)) # prints A\nB\n
for _ in range(2): print(next(cyc2)) # prints C\nD\n
<script src="//repl.it/embed/IRcx/3.js"></script>
使用 copy
模块的解决方法: 一个可能的解决方案是使用 copy.deepcopy
函数。
import itertools, copy
cyc = itertools.cycle('ABCD')
cyc1 = copy.deepcopy(cyc)
cyc2 = copy.deepcopy(cyc)
for _ in range(2): print(next(cyc1)) # prints A\nB\n
for _ in range(2): print(next(cyc2)) # prints A\nB\n
<script src="//repl.it/embed/IRcx/4.js"></script>