Matching Lists: Different behavior regarding volume in debug mode and normal execution mode

Consider the following:

def f():
    a = 2
    b = [a + i for i in range(3)]
f()

This works without a problem. I understand (please correct me if I'm wrong), the expression of understanding the context introduces a new scope, but since it is created inside the function (unlike, say, the class), it has access to the surrounding area, including the variable a.

In contrast, if I were to enter debug mode, stop at line 3 above, and then simply manually write the following in the interpreter

>>> b = [a + i for i in range(3)]

I get an error message:

Traceback (most recent call last):
  File "<string>", line 293, in runcode
  File "<interactive input>", line 1, in <module>
  File "<interactive input>", line 1, in <listcomp>
NameError: global name 'a' is not defined

Why is this? When I stop at a given line in debug mode, is this not an area to which I have access to the same as at runtime?

(By the way, I'm using PyScripter)

+4
2

, .

Python , . , , , , () .

a ; , a f. , , . , a , :

>>> import dis
>>> dis.dis(compile("b = [a + i for i in range(3)]", '<stdin>', 'single').co_consts[0])
  1           0 BUILD_LIST               0
              3 LOAD_FAST                0 (.0)
        >>    6 FOR_ITER                16 (to 25)
              9 STORE_FAST               1 (i)
             12 LOAD_GLOBAL              0 (a)
             15 LOAD_FAST                1 (i)
             18 BINARY_ADD
             19 LIST_APPEND              2
             22 JUMP_ABSOLUTE            6
        >>   25 RETURN_VALUE

A LOAD_GLOBAL - a (.0 range(3) ).

:

>>> def f():
...     a = 2
...     b = [a + i for i in range(3)]
... 
>>> dis.dis(f.__code__.co_consts[2])
  3           0 BUILD_LIST               0
              3 LOAD_FAST                0 (.0)
        >>    6 FOR_ITER                16 (to 25)
              9 STORE_FAST               1 (i)
             12 LOAD_DEREF               0 (a)
             15 LOAD_FAST                1 (i)
             18 BINARY_ADD
             19 LIST_APPEND              2
             22 JUMP_ABSOLUTE            6
        >>   25 RETURN_VALUE
>>> f.__code__.co_cellvars
('a',)

a LOAD_DEREF, ( 'a').

; :

>>> def f(a):
...     return [a + i for i in range(3)]
...
>>> f(a)
[2, 3, 4]
+5

( ). , , , , . , - , . , , , .

-1

Source: https://habr.com/ru/post/1536244/


All Articles