Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 嵌套函数中变量引用和赋值的顺序_Python_Python 3.x_Scope - Fatal编程技术网

Python 嵌套函数中变量引用和赋值的顺序

Python 嵌套函数中变量引用和赋值的顺序,python,python-3.x,scope,Python,Python 3.x,Scope,从词汇范围界定的角度来看: 嵌套Python函数可以引用在封闭函数中定义的变量 功能,但无法分配给它们 此规范可在此处看到: def toplevel(): a = 5 def nested(): # Tries to print local variable `a`, but `a` is created locally after, # so `a` is referenced before assignment. You would nee

从词汇范围界定的角度来看:

嵌套Python函数可以引用在封闭函数中定义的变量 功能,但无法分配给它们

此规范可在此处看到:

def toplevel():
    a = 5
    def nested():
        # Tries to print local variable `a`, but `a` is created locally after,
        # so `a` is referenced before assignment.  You would need `nonlocal a`
        print(a + 2)
        a = 7
    nested()
    return a
toplevel()
# UnboundLocalError: local variable 'a' referenced before assignment
nested
中颠倒两条语句的顺序可以解决此问题:

def toplevel():
    a = 5
    def nested():
        # Two statements' order reversed, `a` is now locally assigned and can
        # be referenced
        a = 7
        print(a + 2)
    nested()
    return a
toplevel()
我的问题是,Python的实现告诉第一个函数,
a
将在本地声明(在print语句之后),这是什么?我的理解是Python是逐行有效解释的。那么,它是否应该默认在代码中的该点查找非本地
a

详细说明一下,如果我只使用引用(没有赋值)

不知何故,print语句知道引用封闭函数中定义的非局部
a
。但是如果我在那一行之后分配给一个本地
a
,这个函数就太聪明了

我的理解是Python是逐行有效解释的

这就是你错的地方。在任何解释开始之前,整个文件被编译成字节码

此外,即使字节码编译过程不存在,
print(a+2)
也不会在看到
a=7
之前执行,因为它在函数定义中。Python在实际尝试执行
print(a+2)

时,仍然知道
a=7

Python的一个特殊怪癖是,如果没有有效的
global
语句,那么对名称的赋值总是进入最内部的范围。赋值不复制数据-它们只是将名称绑定到对象

我的理解是Python是逐行有效解释的

这不是正确的思维模式

对整个函数体进行分析,以确定哪些名称引用局部变量,哪些不引用

为了简化您的示例,下面还提供了
UnboundLocalError

def func():
  print(a)
  a = 2

func()
这里,
func()
编译为以下字节码:

  2           0 LOAD_FAST                0 (a)
              3 PRINT_ITEM
              4 PRINT_NEWLINE

  3           5 LOAD_CONST               1 (2)
              8 STORE_FAST               0 (a)
             11 LOAD_CONST               0 (None)
             14 RETURN_VALUE
将此与

def gunc():
  print(a)
编译成

  2           0 LOAD_GLOBAL              0 (a)
              3 PRINT_ITEM
              4 PRINT_NEWLINE
              5 LOAD_CONST               0 (None)
              8 RETURN_VALUE

观察没有赋值给
a
是如何将引用从本地转到全局的。

可能是指字节码按正确的指令执行的语句。“不是吗?”DeRePrass:它不像你想象的那么正确,因为函数调用(显式的或隐式的,如<代码> +/COD> >)通常会导致字节码指令在其他字节码指令的中间执行,但无论如何,我认为发问者确实是逐行表示的。
  2           0 LOAD_GLOBAL              0 (a)
              3 PRINT_ITEM
              4 PRINT_NEWLINE
              5 LOAD_CONST               0 (None)
              8 RETURN_VALUE