问题
In the following code, both a
and b
are outputs of generator functions, and could evaluate to None
or have a value.
def testBehaviour(self):
a = None
b = 5
while True:
if not a or not b:
continue
print('blaat')
If I put breakpoints (using Visual Studio Code) on the line with the continue
statement, and the line with the print
statement, neither is hit. The print
statement is not called, and the loop just keeps running indefinitely as expected, but I would expect that breakpoints are hit.
If I change the code to one of the following:
def testBehaviour(self):
a = None
b = 5
while True:
if not a:
continue
print('blaat')
or:
def testBehaviour(self):
a = None
b = 5
while True:
if not a or not b:
c = 'dummy'
continue
print('blaat')
And again place breakpoints on the lines with the continue
and print
statements, the breakpoints are hit.
Can anyone tell me why the breakpoints are not hit? It seems to not happen only in Visual Studio Code, because our code-coverage tool also states that the continue
statement was not called.
This is on python 2.7 on Windows 7, 32 bit.
回答1:
There is an optimization in the opcodes, the compiler recognizes the if expr: continue
.
When using if not a or not b:
11 12 SETUP_LOOP 35 (to 50)
>> 15 LOAD_GLOBAL 1 (True)
18 POP_JUMP_IF_FALSE 49
12 21 LOAD_FAST 1 (a)
24 UNARY_NOT
25 POP_JUMP_IF_TRUE 15
28 LOAD_FAST 2 (b)
31 UNARY_NOT
32 POP_JUMP_IF_FALSE 41
13 35 JUMP_ABSOLUTE 15
38 JUMP_FORWARD 0 (to 41)
14 >> 41 LOAD_CONST 2 ('blaat')
44 PRINT_ITEM
45 PRINT_NEWLINE
46 JUMP_ABSOLUTE 15
>> 49 POP_BLOCK
>> 50 LOAD_CONST 0 (None)
53 RETURN_VALUE
The line 25 POP_JUMP_IF_TRUE 15
jumps back to the start of the while loop (line 15) if not a
is true. It never reaches the line of the continue statement 35 JUMP_ABSOLUTE 15
If you switch the values of a
and b
this test case works.
If you rewrite the test expression to if not ( a and b ):
you get the following opcodes
11 12 SETUP_LOOP 33 (to 48)
>> 15 LOAD_GLOBAL 1 (True)
18 POP_JUMP_IF_FALSE 47
12 21 LOAD_FAST 1 (a)
24 JUMP_IF_FALSE_OR_POP 30
27 LOAD_FAST 2 (b)
>> 30 POP_JUMP_IF_TRUE 39
13 33 JUMP_ABSOLUTE 15
36 JUMP_FORWARD 0 (to 39)
14 >> 39 LOAD_CONST 2 ('blaat')
42 PRINT_ITEM
43 PRINT_NEWLINE
44 JUMP_ABSOLUTE 15
>> 47 POP_BLOCK
>> 48 LOAD_CONST 0 (None)
51 RETURN_VALUE
And that always works and is faster. The not
operations are optimized into the jump test statements
来源:https://stackoverflow.com/questions/62387618/breakpoint-on-continue-in-if-statement-not-hit