为什么 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.
为什么会这样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.