意外范围行为的文档
Documentation for unexpected scope behaviour
我今天遇到了一个最初让我感到惊讶的范围界定问题。可以通过以下方式轻松证明:
def scope():
x = 1
def working():
print x
def broken():
import pdb; pdb.set_trace()
working()
broken()
Python 2.7.12 (default, Jul 1 2016, 15:12:24)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
...
>>> scope()
1
--Return--
> <stdin>(6)broken()->None
(Pdb) x
*** NameError: name 'x' is not defined
Python 3.5.2 (default, Sep 10 2016, 08:21:44)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def scope():
...
>>> scope()
1
--Return--
> <stdin>(6)broken()->None
(Pdb) x
*** NameError: name 'x' is not defined
(Pdb)
因此,如果在编译时 明确引用了外部范围值,则范围似乎只会包含外部范围值。这肯定是在查看字节码时似乎发生的事情:
6 0 LOAD_GLOBAL 0 (x)
3 PRINT_ITEM
4 PRINT_NEWLINE
5 LOAD_CONST 0 (None)
8 RETURN_VALUE
这是 Python 如何通过检查绑定函数来区分外部和内部范围引用的产物吗?
Python scoping rules似乎无法解释:
Although scopes are determined statically, they are used dynamically. At any time during execution, there are at least three nested scopes whose namespaces are directly accessible:
- the innermost scope, which is searched first, contains the local names
- the scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also non-global names
我想了解的是上面突出显示的两个部分之间的冲突:作用域是静态的,但似乎并没有兑现可访问名称的承诺。
具体来说,我要查找的是此显式行为的官方文档。
x
不是 broken
的局部变量("local" 表示在函数内部赋值),因此它不会出现在 locals()
中。
但是,如果对象没有被本地覆盖,您可以从外部范围访问对象,因此您可以在 working
.
中访问它
我认为介绍 PEP227(对于 python 2.1!)涵盖了其工作原理的规范。关键部分:
The Python 2.0 definition specifies exactly three namespaces ... the local namespace, the global namespace,
and the builtin namespace. According to this definition, if a
function A is defined within a function B, the names bound in B
are not visible in A. The proposal changes the rules so that
names bound in B are visible in A (unless A contains a name
binding that hides the binding in B).
...
If a name is used within* a code block, but it is not bound there
and is not declared global, the use is treated as a reference to
the nearest enclosing function region.
...
An analogous function [to locals() and globals()] will not be provided for nested scopes. Under this proposal, it will not be possible to gain dictionary-style access to all visible scopes.
* 强调位是关键位:您的变量尚未在代码块中使用,因此没有任何内容可以视为对封闭函数的引用。
此外,pdb
是动态的运行,当没有指定命令时default
(source code link)动作使用exec
与locals
和globals
从框架。因此,它唯一可用的变量是被检查帧的 locals()
和 globals()
,如前所述,它不包括从封闭帧捕获的变量。
我今天遇到了一个最初让我感到惊讶的范围界定问题。可以通过以下方式轻松证明:
def scope():
x = 1
def working():
print x
def broken():
import pdb; pdb.set_trace()
working()
broken()
Python 2.7.12 (default, Jul 1 2016, 15:12:24)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
...
>>> scope()
1
--Return--
> <stdin>(6)broken()->None
(Pdb) x
*** NameError: name 'x' is not defined
Python 3.5.2 (default, Sep 10 2016, 08:21:44)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def scope():
...
>>> scope()
1
--Return--
> <stdin>(6)broken()->None
(Pdb) x
*** NameError: name 'x' is not defined
(Pdb)
因此,如果在编译时 明确引用了外部范围值,则范围似乎只会包含外部范围值。这肯定是在查看字节码时似乎发生的事情:
6 0 LOAD_GLOBAL 0 (x)
3 PRINT_ITEM
4 PRINT_NEWLINE
5 LOAD_CONST 0 (None)
8 RETURN_VALUE
这是 Python 如何通过检查绑定函数来区分外部和内部范围引用的产物吗?
Python scoping rules似乎无法解释:
Although scopes are determined statically, they are used dynamically. At any time during execution, there are at least three nested scopes whose namespaces are directly accessible:
- the innermost scope, which is searched first, contains the local names
- the scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also non-global names
我想了解的是上面突出显示的两个部分之间的冲突:作用域是静态的,但似乎并没有兑现可访问名称的承诺。
具体来说,我要查找的是此显式行为的官方文档。
x
不是 broken
的局部变量("local" 表示在函数内部赋值),因此它不会出现在 locals()
中。
但是,如果对象没有被本地覆盖,您可以从外部范围访问对象,因此您可以在 working
.
我认为介绍 PEP227(对于 python 2.1!)涵盖了其工作原理的规范。关键部分:
The Python 2.0 definition specifies exactly three namespaces ... the local namespace, the global namespace, and the builtin namespace. According to this definition, if a function A is defined within a function B, the names bound in B are not visible in A. The proposal changes the rules so that names bound in B are visible in A (unless A contains a name binding that hides the binding in B).
...
If a name is used within* a code block, but it is not bound there and is not declared global, the use is treated as a reference to the nearest enclosing function region.
...
An analogous function [to locals() and globals()] will not be provided for nested scopes. Under this proposal, it will not be possible to gain dictionary-style access to all visible scopes.
* 强调位是关键位:您的变量尚未在代码块中使用,因此没有任何内容可以视为对封闭函数的引用。
此外,pdb
是动态的运行,当没有指定命令时default
(source code link)动作使用exec
与locals
和globals
从框架。因此,它唯一可用的变量是被检查帧的 locals()
和 globals()
,如前所述,它不包括从封闭帧捕获的变量。