Python 中的全局变量和局部变量
内置函数 globals()
和 locals()
分别返回全局符号表和局部符号表。Python 解释器维护一个数据结构,其中包含程序源代码中出现的每个标识符的信息。这些信息包括标识符(也称为符号)的类型、值、作用域级别和位置。
编译器/解释器将这些符号表用于各种目的,例如
- 存储所有实体,以便高效检索。
- 验证对象是否已声明。
- 确定对象的作用域。
- 类型检查和语义准确性。
Python 解释器使用 字典 对象来保存这些信息。如上所述,这些符号可以是 变量、函数 和 类 等。这些在模块级别(Python 的交互式控制台也被视为模块级别)可供解释器使用的符号集合存储在 globals()
函数返回的字典中。
考虑以下示例
>>> num1=100
>>> num2=200
>>> name="TutorialsTeacher"
>>> 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': 'TutorialsTeacher'}
在模块级别和 交互式 shell 环境中,locals()
函数也返回相同的字典。
>>> locals()
<pre className="language-python"><code>>>> 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': 'TutorialsTeacher'}
让我们通过修改 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': 'TutorialsTeacher'}
local symbol table: {'x': 100, 'y': 200, 'z': 300}
如您所见,全局符号表保持不变。但是,当通过传递 num1
和 num2
调用 add()
函数时,它们的值被赋给形式参数变量 x
和 y
,它们是 add()
函数的局部变量。因此,局部表会随 x
、y
和 z
进行更新。
请注意,如果一个变量已存在于全局作用域中,并且也在函数的局部作用域中声明,则编译器会在局部作用域中赋予优先级。此外,在函数内部更改其值不会影响其在全局空间中的值。
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
<div className="card-header example-header"><div className="example-caption">Example: Modify Global Dictionary </div><button className="copy-btn pull-right" title="Copy example code"><i className="fa fa-copy"></i> Copy</button></div>
<div className="panel-body">
<pre className="language-python"><code>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
<div className="card-header example-header"><div className="example-caption">Example: global keyword </div><button className="copy-btn pull-right" title="Copy example code"><i className="fa fa-copy"></i> Copy</button></div>
<div className="panel-body">
<pre className="language-python"><code>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
在嵌套函数的情况下,通过声明为 global,可以在内部函数中使用外部函数命名空间中存在的变量。
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
关键字,它允许在全局(外部空间)声明的变量。
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
,但 withoutnolocal()
内部没有 nolocal
的更改不会反映。