可以在循环中跳到第n次迭代吗?

4 投票
2 回答
3243 浏览
提问于 2025-04-19 20:05
42 -> for i in range(n):
43       foo(i)

我现在正在使用pdb调试工具,想要直接跳到循环中当i = k的那次迭代,而不想先执行foo(i)i小于k的部分,然后再继续执行foo(i)i大于k的部分。如果我向前一步到

42    for i in range(n):
43 ->    foo(i)

设置i = k,然后continue,那么在下一次迭代时i会回到1。我能不能让它直接跳到k + 1呢?

2 个回答

1

我现在不能测试这个,但我相信你可以使用 condition 命令:

condition bpnumber [condition]
这里的条件是一个表达式,只有当它的结果为真时,断点才会生效。如果没有提供条件,那么就会移除任何已有的条件;也就是说,断点会变成无条件的。

condition <插入行号> i == k

4

你不能“跳过”某些步骤,也不能往回走。你只能按照写好的循环来执行;要到达第 k 次循环,你必须经过所有中间步骤。这是因为Python无法知道在不同的循环之间状态是否会发生大变化,所以你不能随便决定跳过某些循环。

不过,你可以在上下文中执行单独的表达式。比如,你可以运行 foo(k) 并观察返回的值。你甚至可以操作很多状态。只是你不能直接进入 for 循环使用的迭代器对象去跳过某些步骤。

如果在运行调试器之前修改测试代码是可行的,你可以和 for 循环共享迭代器:

r = range(n)
it = iter(r)
for i in it:
    foo(i)

这样你就可以把 it 提前推进到某个点(比如用 next(it))。问题是,你不能像那样倒回去。

接下来的步骤是制作一个可以倒回的自定义迭代器:

class ControllableIterator(object):
    def __init__(self, sequence):
        self.pos = 0
        self.seq = sequence
    def __iter__(self): return self
    def next(self):
        try:
            val = self.seq[self.pos]
        except IndexError:
            raise StopIteration
        self.pos += 1
        return val
    __next__ = next  # Python 3

然后使用这个:

r = range(n)
it = ControllableIterator(r)
for i in it:
    foo(i)

在这里你可以把 it.pos 设置为不同的值,for 循环会顺利跟上。这 仅适用于序列,而不是任何可迭代对象。

演示:

$ bin/python test.py 
> /Users/mj/Development/venvs/stackoverflow-2.7/test.py(19)<module>()
-> r = range(100)
(Pdb) l
 14     
 15     def foo(i):
 16         print i
 17     
 18     import pdb; pdb.set_trace()
 19  -> r = range(100)
 20     it = ControllableIterator(r)
 21     for i in it:
 22         foo(i)
 23     
[EOF]
(Pdb) n
> /Users/mj/Development/venvs/stackoverflow-2.7/test.py(20)<module>()
-> it = ControllableIterator(r)
(Pdb) 
> /Users/mj/Development/venvs/stackoverflow-2.7/test.py(21)<module>()
-> for i in it:
(Pdb) 
> /Users/mj/Development/venvs/stackoverflow-2.7/test.py(22)<module>()
-> foo(i)
(Pdb) 
0
> /Users/mj/Development/venvs/stackoverflow-2.7/test.py(21)<module>()
-> for i in it:
(Pdb) 
> /Users/mj/Development/venvs/stackoverflow-2.7/test.py(22)<module>()
-> foo(i)
(Pdb) 
1
> /Users/mj/Development/venvs/stackoverflow-2.7/test.py(21)<module>()
-> for i in it:
(Pdb) it.pos = 50
(Pdb) n
> /Users/mj/Development/venvs/stackoverflow-2.7/test.py(22)<module>()
-> foo(i)
(Pdb) 
50
> /Users/mj/Development/venvs/stackoverflow-2.7/test.py(21)<module>()
-> for i in it:

撰写回答