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

2024-06-16 11:15:27 发布

您现在位置:Python中文网/ 问答频道 /正文

从词汇范围的Google Style Guide开始:

A nested Python function can refer to variables defined in enclosing functions, but can not assign to them.

此规范可在此处看到:

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吗?你知道吗

更详细地说,如果我使用只是引用(没有赋值)

def toplevel():
    a = 5
    def nested():
        print(a + 2)
    nested()
    return a
toplevel()

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


Tags: to函数returnislocaldef语句variable
3条回答

根据document

A special quirk of Python is that – if no global statement is in effect – assignments to names always go into the innermost scope. Assignments do not copy data — they just bind names to objects.

My understanding is that Python is effectively interpreted line by line.

这不是正确的思维模式。你知道吗

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

为了简化示例,下面还提供了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是如何将引用从局部转到全局的。你知道吗

My understanding is that Python is effectively interpreted line by line

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

而且,即使字节码编译过程不存在,print(a + 2)也不会在看到a = 7之前执行,因为它在函数定义中。Python在实际尝试执行print(a + 2)时仍然知道a = 7。你知道吗

相关问题 更多 >