Python 2.7 我可以在for循环体中重新定义迭代器变量吗?
下面是一个人为的例子:Python 2.7 我可以在for循环体中重新定义迭代器变量吗?,python-2.7,for-loop,scope,iterator,Python 2.7,For Loop,Scope,Iterator,下面是一个人为的例子: from itertools import cycle def foobar(): A = [1,2,3,4,5] B = [6,7,8,9,10] it = cycle(A) tmp=0 for item in it: print item, tmp if tmp>10: it=cycle(B) #is this possible? if tmp>
from itertools import cycle
def foobar():
A = [1,2,3,4,5]
B = [6,7,8,9,10]
it = cycle(A)
tmp=0
for item in it:
print item, tmp
if tmp>10:
it=cycle(B) #is this possible?
if tmp>30:
return tmp
tmp+=item
输出:
1 0
2 1
3 3
4 6
5 10
1 15
2 16
3 18
4 21
5 25
1 30
2 31
1 0
2 1
3 3
4 6
5 10
1 15
6 16
7 22
8 29
9 37
我试图迭代for循环中的一个iterable,直到满足一个条件,在这个条件下,我重新定义它,使它使用相同的循环体迭代另一个列表
代码的运行方式与我希望的不同:它继续使用cycle(A),即使在我重新定义它=cycle(B)之后也是如此。我认为存在某种范围问题,循环中的代码无法修改循环条件。是否有任何方法可以完成我在这里尝试的操作,或者是否需要对循环进行复制或嵌套,以便在多个列表上进行迭代?无法直接完成您想要的操作。代码中的
for
循环仅引用首次启动时传递的iterable的初始值。它对该iterable调用iter()
,并使用它得到的迭代器来获取要迭代的项。重新绑定在的中使用的变量不会改变任何东西,因为循环的内部逻辑在获得迭代器后不会使用该变量
我怀疑使用break
和另一个循环将是解决此问题的最佳方法。但是,如果您真的希望使循环代码尽可能接近当前的代码,您可以编写自己的迭代器,以便根据需要从一个(内部存储的)迭代器切换到另一个迭代器:
class swapable_iterator(object):
def __init__(self, it):
self.it = it
def __iter__(self):
return self
def next(self):
return next(self.it)
__next__ = next # Python 3 compatibility
def swap(self, new_it):
self.it = new_it
您仍然需要稍微更改一下循环逻辑,因为当前它将反复切换到循环(B)
(在tmp>10
之后),只会看到第一个值
尝试以下方法:
def foobar():
A = [1,2,3,4,5]
B = [6,7,8,9,10]
it = swapable_iterator(cycle(A)) # wrap the cycle with our custom iterator object
tmp=0
for item in it:
print item, tmp
if item == 5 and tmp > 10: # this will happen exactly once with the A and B above
it.swap(cycle(B)) # this modifies "it" in place, rather than rebinding it
if tmp>30:
return tmp
tmp+=item
我认为不可能改变for循环的条件。您可以始终使用while和一些语句来更改要使用的迭代器的下一项,例如:
from itertools import cycle
def foobar():
A = [1, 2, 3, 4, 5]
B = [6, 7, 8, 9, 10]
tmp = 0
iter_A = cycle(A)
iter_B = cycle(B)
use_A = True
while True:
if use_A:
item = next(iter_A)
else:
item = next(iter_B)
print item, tmp
if tmp > 10:
use_A = False
if tmp > 30:
return tmp
tmp += item
输出:
1 0
2 1
3 3
4 6
5 10
1 15
2 16
3 18
4 21
5 25
1 30
2 31
1 0
2 1
3 3
4 6
5 10
1 15
6 16
7 22
8 29
9 37
我希望这有帮助
更新:
根据Martijn Pieters的评论,以下内容也应适用:
from itertools import cycle
def foobar():
A = [1, 2, 3, 4, 5]
B = [6, 7, 8, 9, 10]
tmp = 0
iter_A = cycle(A)
iter_B = cycle(B)
it = iter_A
while True:
item = next(it)
print item, tmp
if tmp > 10:
it = iter_B
if tmp > 30:
return tmp
tmp += item
那很有趣。但是,可交换迭代器真的可以工作吗?如果for循环使用的是iter()
的结果,那么调用it.swap
似乎会遇到与以前相同的问题,即它不会导致for循环重新计算迭代器并更改循环条件。感谢您的回答它是一个迭代器,因此它的iter\uuuu
方法返回self
。无法在原始代码中交换它
(作为循环
,它也是一个迭代器,它的\uuuuuu iter\uuuuuuuu方法返回self
),原因是您正在重新绑定名称它
,而不是修改迭代器。调用it.swap
(当it
是一个可交换迭代器时)将对其进行适当的修改,因此循环将根据需要拾取更改。不使用标志,只需使用it=iter\u a
,然后切换到it=iter\u B
。