意外范围行为的文档

时间:2016-11-22 07:10:44

标签: python scope documentation

我今天遇到一个范围问题,最初让我感到惊讶。它可以通过以下方式轻松证明:

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

似乎没有解释这一点
  

虽然范围是静态确定的,但它们是动态使用的。在执行期间的任何时间,至少有三个嵌套作用域,其名称空间可以直接访问:

     
      
  • 首先搜索的最里面的范围包含本地名称
  •   
  • 从最近的封闭范围开始搜索的任何封闭函数的范围包含非本地名称,但也包含非全局名称
  •   

我试图理解的是上面两个突出部分之间的冲突:范围是静态的,但似乎可以维护可访问名称的承诺。

具体来说,我正在寻找的是这种明确行为的官方文档。

2 个答案:

答案 0 :(得分:2)

x不是broken的本地人(&#34;本地&#34;意味着在函数内分配),因此它不会显示在locals()中。

但是,如果对象没有被本地阴影,则可以从外部作用域访问对象,因此您可以在working中访问它。

答案 1 :(得分:1)

我认为介绍What is the difference between should and must in scala testing?(对于python 2.1!)涵盖了如何工作的规范。关键部分:

  

Python 2.0定义正好指定了三个名称空间......本地名称空间,全局名称空间,       和内置命名空间。根据这个定义,如果一个       函数A在函数B中定义,名称在B中绑定       在A中不可见。提案会更改规则以便这样做       B中绑定的名称在A中可见(除非A包含名称       在B)中隐藏绑定的绑定。

     

...

     

如果在 *代码块中使用名称,但它没有绑定       并且未声明为全局,该用途被视为对其的引用       最近的封闭功能区。

     

...

     

不会为嵌套作用域提供类似函数[ to locals()和globals()]。根据此提案,将无法获得对所有可见范围的字典式访问。

*强调位为关键位:您的变量未在代码块中使用,因此没有什么可以作为对封闭函数的引用。

此外,pdb动态运行,未指定命令时PEP227操作使用execlocals来自框架globals。因此,唯一可用的变量是被检查帧的locals()globals(),如图所示,不包括从封闭帧中捕获的变量。