Breakpoint on continue in if statement not hit

不打扰是莪最后的温柔 提交于 2021-01-27 18:42:54

问题


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

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