Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 2.7 我可以在for循环体中重新定义迭代器变量吗?_Python 2.7_For Loop_Scope_Iterator - Fatal编程技术网

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