Python 中的 globals() 和 locals() 方法

2023-09-21 10:32:24

内置函数globals()locals()分别返回全局和局部符号表。Python 解释器维护一个数据结构,其中包含有关程序源代码中出现的每个标识符的信息。此信息与标识符(也称为符号)的类型、值、范围级别和位置有关。

编译器/解释器将这些符号表用于各种目的,例如:

  1. 存储高实体,以便可以有效地检索它们。
  2. 验证是否已声明对象。
  3. 确定对象的作用域。
  4. 类型检查和语义准确性。

Python 解释器使用 dictionary 对象来保存此信息。 如上所述,符号可以是variablesfunctionsclasses等。 解释器在模块级别可用的这种符号集合(Python 的交互式控制台也被视为模块级别)存储在 globals() 函数返回的字典中。

请考虑以下示例:

>>> num1=100
>>> num2=200
>>> name="python114.com"
>>> def add(x,y):
        z=x+y
        return z
    
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, 
'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'num1': 100, 'num2': 200, 
'add': <function add at 0x000001E63FBE1AF8>, 'name': 'python114.com'}

在模块级别和interactive shell环境中,locals()函数也返回相同的字典。

>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, 
'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'num1': 100, 'num2': 200, 
'add': <function add at 0x000001E63FBE1AF8>, 'name': 'python114.com'}

让我们通过修改add()函数来检查这些函数从函数内部返回的内容,如下所示:

>>> def add(x,y):
        z=x+y
        print ('global symbol table:', globals())
        print ('local symbol table:', locals())
        return z
>>> add(num1, num2)   
global symbol table: {'__name__': '__main__', '__doc__': None, '__package__': None, 
'__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, 
'__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 
'num1': 100, 'num2': 200, 'add': <function add at 0x000001E63FBD15E8>, 'name': 'python114.com'}
local symbol table: {'x': 100, 'y': 200, 'z': 300}

如您所见,全局符号表保持不变。然而,当通过传递num1num2调用add()函数时,它们的值被分配给形式参数变量xy,它们是add()函数的局部变量。 因此,本地表更新为 xyz

请注意,如果全局作用域中已经存在的变量也在函数的局部作用域中声明,则编译器会在局部作用域中指定优先级。此外,函数内部值的变化不会影响它在全局空间中。

x=10
def myfunction():
    x=10
    x=x*2
    print ('x inside function: ', x)
myfunction()
print ('x in global scope: ',x)

输出:

x inside function: 20
x in global scope: 10

我们可以使用 globals() 字典修改全局变量,如下所示。

x=10
def myfunction():
    x=globals()['x']
    x=x*2
    globals()['x']=x                  
    print ('global variable x inside function: ',x)
    return
myfunction()
print ('global variable x in global scope: ',x)

输出:

global variable x inside function:  20
global variable x in global scope:  20

Python还有一个global关键字。它允许在函数中使用和修改全局声明的变量,确保修改也全局反映。

x=10
def myfunction():
    global x
    x=x*2                  
    print ('global variable x inside function: ',x)
    return
myfunction()
print ('global variable x in global scope: ',x)

输出:

global variable x inside function: 20
global variable x in global scope: 20

在嵌套函数的情况下,外部函数命名空间中存在的变量可以通过声明全局在内部函数中使用。

def outer(): 
     x1 = 15
     print ('in outer function:',x1)  
     def inner(): 
            global x1
            x1 = 30
            print ('value inside function',x1)
            
            
     inner() 
     print("After inner function: ", x1) 
  
outer() 
print("value of x1",x1) 

输出:

in outer function: 15
value inside function 30
After inner function:  15
value of x1 30

Python 也有 nolocal 关键字,允许在全局(外太空)中声明变量。

def outer(isnolocal):
    x2=100
    print ('value in outer function:',x2)
    
    def withnolocal():
        nonlocal x2
        x2=50
    
    def withoutnolocal():
        x2=50
    
    if isnolocal==True:
        withnolocal()
    else:
        withoutnolocal()
    
    return x2
        
print (outer(True))
print (outer(False))

输出:

value in outer function: 100
50
value in outer function: 100
100

上面,outer()函数有两个嵌套函数。两者都尝试修改在外部函数中声明的变量。我们可以看到,具有nolocal x2声明的内部函数withnolocal可以修改外部变量x2,但是没有nolocalwithoutnolocal()内部的变化不会反映出来。