问题
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