【问题标题】:Functions Namespace concept (referenced before assignment)函数命名空间概念(赋值前引用)
【发布时间】:2018-03-16 19:09:45
【问题描述】:

我在函数中寻找一些关于命名空间概念的解释。

这是一个会引发 UnboundLocalError: local variable … referenced before assignment

的代码
x = 1
def foo():
    print x
    x = 2

我知道这应该引发异常。但我想了解 python 如何知道变量在本地命名空间中。在行 print x 处,x 不在局部变量 dict 中。

x = 1
def foo():
    print 'local before print x : ',locals()
    print x
    print 'local after print x :',locals()
    x = 2

foo() # call function, print local namespace before raising exception
local before print x :  {}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in foo
UnboundLocalError: local variable 'x' referenced before assignment

在 print x 之前,local namespace dict 是空的 {}(这很明显)。那么python怎么知道x是局部变量呢。

这与类的工作方式不同

a = [1]
class b():
    c = a
    a = 2

print 'c inside class ', b.c
'c inside class  [1]'

d = b()

类中类似情况不会引发异常。

如果有人可以帮我解释概念,python如何在赋值之前知道这个变量是局部变量。

我检查了许多表格和网站的解释,但没有找到任何解释。

有解释如何解决这种情况的帖子和表格。例子。 UnboundLocalError: local variable … referenced before assignment 。 但我正在寻找 python 在后面工作。

【问题讨论】:

    标签: python python-2.7 function namespaces local-variables


    【解决方案1】:

    Python 将您的代码预编译成一些字节码。在这一步中,它将为每个范围(通常是函数)找出标识符是引用全局变量还是局部变量。

    • 如果明确声明为global,则它是全局的(简单的情况)。
    • 如果在函数中任何地方为其分配了一个值而没有明确声明global,则它是本地的。
    • 如果仅在函数中读取,则假定为全局(隐式)。

    这是在编译时完成的,因此不会执行任何操作来确定这一点。

    现在,在运行时,如果您在分配局部变量之前读取它,您会得到错误。

    现在,对于类,您会遇到不同的情况,因为那里的变量并不是真正的本地变量(即位于调用堆栈的内存中)。如果您在b 的声明中访问 a,您将访问模块全局变量,除非存在覆盖模块全局变量的类全局变量。如果您分配a,您将创建(或更改)一个类全局变量。对a 的任何后续访问(或分配给)都将访问全局类(或分配给)。

    【讨论】:

    • 是的,我完全同意你的看法。但是当我在打印该变量之前print locals() 时,它会给出空字典。那么如果不是局部变量,python 会在哪里寻找局部变量。
    • 它不会同时查看两者。如果编译步骤发现它应该是一个局部变量(使用上面概述的确定性),它将查看locals()。如果变量在编译时被确定为全局变量,它将查看globals()。如果在 there 没有找到它,则抛出异常。如果在locals() 中找不到globals(),则没有“回退”,反之亦然。
    • 对于可以具有局部变量的函数来说,所有这些都是正确的。对于课程,您有不同的概念;没有“局部”变量,只有类全局变量(与模块全局变量相对)。在这种情况下,您拥有回退和覆盖机制(第一类全局变量和替代模块全局变量),您错误地认为在函数中具有局部变量和全局变量。
    • 该信息存储在生成的字节码中。它将包含用于访问堆栈上的局部变量或用于访问全局变量的代码。这使得在运行时很难“找出”(如果这是您的目标,我不确定您的用例,但听起来有点像这样)。您可以访问 try 类中的变量并检查错误以防它不可用。局部变量和全局变量的消息可能不同。
    • 我没有接受它,因为你的答案不是我想要的。从您的 cmets 中可以清楚地看到。这就是为什么我对你的 cmets 投票有用。 docs.python.org/2.7/tutorial/… 让我更清楚。
    猜你喜欢
    • 2021-08-29
    • 2013-10-17
    • 1970-01-01
    • 2018-01-14
    • 2015-05-14
    • 1970-01-01
    • 2023-03-10
    • 2020-10-11
    • 1970-01-01
    相关资源
    最近更新 更多