为什么 pdb 会为列表理解的 "if" 子句中引用的变量提供 NameError?

Why does pdb give NameError for variables referenced in "if" clause of list comprehension?

为什么会这样NameError

(为了便于阅读,插入提示前的空行。)

$ python3
Python 3.4.10 (default, Oct  4 2019, 19:39:58)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-23)] on linux
Type "help", "copyright", "credits" or "license" for more information.

>>> import pdb

>>> def blah():
...     foo = "ab"
...     pdb.set_trace()
... 

>>> blah()
--Return--
> <stdin>(3)blah()->None

(Pdb) [bar for bar in "ac" if bar in foo]
*** NameError: name 'foo' is not defined

以下所有工作正常:

(Pdb) foo
'ab'

(Pdb) [bar for bar in foo]
['a', 'b']

(Pdb) [bar for bar in "ac" if bar in "ab"]
['a']

因此,对于在 if 子句中引用的变量,其他 而不是循环变量本身,这是一个特别的问题。

python 3.6.9 (default, Apr 18 2020, 01:56:04).

中也可以看到与上述相同的行为

但在 python 2(2.6.6 或 2.7.17)中,使用与上述相同的命令,我得到:

(Pdb) [bar for bar in "ac" if bar in foo]
['a']

List comprehensions in Python3 are evaluated with a separate scope, similar to functions. Only the first iterable (for ... in iterable) is injected from the outside, all other names are bound as globals or closures. However, closures are resolved at compile time – they only work when lexically defined in the outer scope containing a name.

将此与定义“内部”函数进行比较,后者表现出相同的行为:

-> pdb.set_trace()
(Pdb) foo
'ab'
(Pdb) def bar(): return foo
(Pdb) bar()
*** NameError: name 'foo' is not defined

在 PDB 会话中,执行范围blah内部,但词法范围在外部。这类似于在其父函数内部或外部定义“内部”function/comprehension:

# lexically scoped `foo` as closure
def blah():
    foo = 3
    def bar():  # !!! Define new scope inside blah
        print(foo)
    bar()  # execute bar inside blah

# `foo` not in scope
def bar():  # !!! Define new scope outside blah
    print(foo)

def blah():
    foo = 3
    bar()  # execute bar inside blah

6.2.4. Displays for lists, sets and dictionaries

[...]

However, aside from the iterable expression in the leftmost for clause, the comprehension is executed in a separate implicitly nested scope. This ensures that names assigned to in the target list don’t “leak” into the enclosing scope.

4.2.2. Resolution of names

[...]

When a name is used in a code block, it is resolved using the nearest enclosing scope. The set of all such scopes visible to a code block is called the block’s environment.