Python 函数名称空间概念(赋值前引用)

Python 函数名称空间概念(赋值前引用),python,python-2.7,function,namespaces,local-variables,Python,Python 2.7,Function,Namespaces,Local Variables,我正在寻找一些关于函数中名称空间概念的解释 下面是一个将引发UnboundLocalError的代码:局部变量…在赋值之前引用 我理解这应该引起例外。但我想了解python是如何知道is变量在本地名称空间中的。在打印x行,x不在局部变量dict中 x = 1 def foo(): print 'local before print x : ',locals() print x print 'local after print x :',locals() x = 2

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

下面是一个将引发UnboundLocalError的代码:局部变量…在赋值之前引用

我理解这应该引起例外。但我想了解python是如何知道is变量在本地名称空间中的。在打印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
课堂上没有出现类似情况的例外

若有人能帮我解释这个概念,python在赋值之前是如何知道这个变量是局部变量的

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

有一些帖子和表格解释了如何解决这个问题。例子。 .
但我正在寻找背后的python

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

  • 如果显式声明为
    global
    ,则它是全局的(简单情况)
  • 如果在函数中的任何位置分配了一个值,而没有显式声明
    global
    ,则该值是本地值
  • 如果它仅在函数中读取,则假定它是全局的(隐式的)
这是在编译时完成的,因此不执行任何操作来确定这一点

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


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

是的,我完全同意您的看法。但是,当我在打印变量之前打印局部变量()时,它会给出空的dict。那么,如果不是在局部变量中,python在哪里查找局部变量呢?它不会同时查找这两个变量。如果编译步骤发现它应该是一个局部变量(使用上面描述的决定论),它将研究
locals()
。如果变量在编译时被确定为全局变量,它将查看
globals()
。如果在那里找不到,则抛出异常。如果在
locals()
中找不到
globals()。对于课堂,你有一个不同的概念;没有“局部”变量,只有类全局变量(与模块全局变量相同)。在这种情况下,您有回退和覆盖机制(第一类全局变量和下沉模块全局变量),您错误地认为at函数具有局部变量和全局变量。该信息存储在生成的字节码中。它要么包含用于访问堆栈上的局部变量的代码,要么包含用于访问全局变量的代码。这使得在运行时很难“发现”(如果这是您的目标,我不确定您的用例,但听起来有点像这样)。您可以在
try
类别中访问该变量,并在该变量不可用时检查错误。对于局部变量和全局变量,消息可能有所不同。我没有接受它,因为您的答案不是我想要的答案。从你的评论中可以清楚地看到。这就是为什么我对你的评论投了有用的票。让我更清楚一点。
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
a = [1]
class b():
    c = a
    a = 2

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

d = b()