Can you jump to the nth iteration in a loop?

和自甴很熟 提交于 2020-05-08 18:00:27

问题


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

Here I am, in the middle of a pdb session. I want to jump to the loop iteration with i = k, without evaluating foo(i) for i < k, AND then continue evaluating foo(i) for i > k. If I step forward a line to

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

set i = k, and continue, then i goes back to 1 at the next iteration. Can I make it go to k + 1 instead?


回答1:


You cannot 'skip forward' and back, no. You can only execute the loop as written; to get to iteration k you'll have to pass through all intermediate steps. That's because Python has no way of knowing if the state is going to alter radically between iterations, you cannot just decided to skip iterations there.

You can always execute individual expressions in the context. You can run foo(k) and observe the returned value. You can even manipulate a lot of state. You just cannot reach into the iterator object used by for to skip ahead.

If altering the code under test before running the debugger is an option, you can share the iterator with the for loop:

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

and now you could advance it to a later point (with next(it), for example). The problem is that you cannot rewind an iterator like that.

The next step would be to produce a custom iterator that can be rewound:

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

and use that:

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

Here you can set it.pos to a different value and for will happily follow along. This only works for sequences, not just any iterable.

Demo:

$ 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:



回答2:


I can't test this right now, but I believe that you can use the condition command:

condition bpnumber [condition]
Condition is an expression which must evaluate to true before the breakpoint is honored. If condition is absent, any existing condition is removed; i.e., the breakpoint is made unconditional.

condition <insert line num> i == k



来源:https://stackoverflow.com/questions/25668194/can-you-jump-to-the-nth-iteration-in-a-loop

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!