python-意外范围行为的文档

我今天遇到了一个范围界定问题,最初使我感到惊讶.以下内容可以很容易地证明这一点:

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

我想了解的是上面两个突出显示的部分之间的冲突:作用域是静态的,但是似乎不支持对可访问名称的承诺.

具体来说,我要寻找的是有关此明确行为的官方文档.

解决方法:

我认为引入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(),如所示,它们不包括从封闭的帧中捕获的变量.

上一篇:python-sphinx:格式化多行文档字符串


下一篇:为什么在CPython退出时没有释放所有内存?