在 python 中从全局范围解析变量

resolving variables from global scope in python

我正在尝试更好地理解 python 中的范围界定。我有以下玩具示例:

a = 1
print "in global: " + str(a)

def g():
    a += 1
    print "in g(): " + str(a)


def f():
    a += 1
    print "in f(): " + str(a)
    g()

f()

我希望这个 运行 并打印出 1 然后 2 然后再次 2 。但是,我得到了 en error:

UnboundLocalError: local variable 'a' referenced before assignment

我原以为 g()f() 都会从全局范围中拉出 a。不正确?

更新: 感谢您的回答,但不清楚的是:如果我只想读取全局变量 a 并将其分配给我创建的局部变量,也命名为 a 这可能吗?

我这样做的原因是我想弄清楚 g() 是在调用时继承 f() 的范围还是在定义它的全局范围内?

您需要使用 global 关键字。

>>> a = 1         
>>> def g():      
...     global a  
...     a += 1    
...     print a   
...               
>>> g()           
2    

您在函数 g 和 f 中缺少全局运算符 像这样:

a = 1

def g():
    global a
    a += 1
    print "in g(): " + str(a)

def f():
    global a
    a += 1
    print "in f(): " + str(a)

您可以在 documentation here and from stack overflow here

中找到有关全局变量和局部变量的更多信息

您正试图在函数的外部范围内更改 aa 不在当前函数的范围内,这就是您收到此类错误的原因,因为您的函数对此一无所知a。如果你想在函数中改变 a 你需要使用 `global':

a = 1
print "in global: " + str(a)

def g():  
    global a
    a += 1
    print "in g(): " + str(a)


def f():
    global a
    a += 1
    print "in f(): " + str(a)
    g()

要打印出全局 a 可以这样使用:

def f():
    print a
    new_a = a
    print new_a

有一个很好的例子global here

如果您想使用局部变量 a 和全局 a 的值,请使用 globals:

def g():  
    a = globals()['a']
    a += 1
    print "in g(): " + str(a)

当您请求变量值时,Python 遵循 LEGB 规则:本地、封闭、全局、内置。

但是当你分配一个变量时,它是在本地范围内从头开始创建的(假设变量分配是在函数内部),丢弃之前绑定到它的任何值:

a = 5
def f(x):
   print a  # Prints `5`, because name `a` can be found following LEGB rule in Global scope.
   print x  # Prints whatever value `x` was having, found following LEGB rule in Local scope.
   x = 123  # Forgets previous value of `x`, re-assign it to `123` in the Local scope.

你的未绑定变量问题出现在这里:a += 1 只是 a = a + 1 的语法糖。当您执行 a = a + 1 时,Python 捕获 a 是本地的,因此它会在字节码中生成 LOAD_FAST 命令:

import dis
a = 1
def f():
  a += 1
print dis.dis(f)

          0 LOAD_FAST                0 (a)
          3 LOAD_CONST               1 (1)
          6 INPLACE_ADD
          7 STORE_FAST               0 (a)
         10 LOAD_CONST               0 (None)
         13 RETURN_VALUE

LOAD_FAST用于获取局部变量。但是当调用 LOAD_FAST 时,您在本地范围内还没有 a,因此命令失败。

实际上,如果您不分配给 a,但想从本地范围修改它,您可以通过方法调用来完成。不幸的是,int 没有修改方法,所以我将举一个例子 class:

class Number(object):
    def __init__(self, x):
        self.x = x
    def add_one(self):
        self.x += 1

a = Number(1)
def f():
    a.add_one()
    print a.x


print a.x
f()
print a.x

1
2
2

在这里,您实际上是 a=a+1,但方式更复杂。这是因为对 a 的调用被解析为全局(并且工作正常)并且您没有在 f() 中进行任何分配。方法 add_one 在现有对象上调用 - 它不关心它在调用者中是全局的还是局部的。