Python的作用域,你了解多少呢?在Python中,代码格式是由严格的缩进级别控制的,保证了较好的可读性。在Java中,若在一个方法(main方法、成员方法、静态方法)中使用了一对大括号,那么这对大括号内部就是一个新的作用域,在这段作用域内部声明的变量外部是无法访问的。
java 代码:public class Main {
public static void main(String[] args) {
{
int a = 1;
}
a = 2;
}
}
上方代码在第6行给a重新赋值时因为a在作用域外因此访问失败,编译不通过。
在Python中,作用域分为4部分:
- 局部作用域,即函数中、类中定义的变量;
- 若该函数或类有父层函数或父层类,则父层函数或父层类具有父层的局部作用域;
- 若函数或类位于顶层,则再上层就为模块级别,此级别的变量为全局变量;
- Python还具有一个内置模块builtin.py,它里面存在着一些预定义的函数的变量,可直接访问到,这部分为内置作用域。
需要注意的是,在日常开发中我们常常定义函数、定义类,它们是会创建新的作用域的,但是使用try-catch、if、for等语法时是不会创建新的作用域的。如:
python 代码:try:
a = 1
except:
...
print(a) # 1
for _ in range(1):
b = 2
print(b) # 2
if True:
c = 3
print(c) # 3
而创建类、创建函数时会创建新的作用域,在外部尝试引用是会抛出异常的。
python 代码:try:
class Demo:
a = 1
print(a)
except Exception as e:
print(e)
try:
def f():
b = 2
print(b)
except Exception as e:
print(e)
运行结果如下。

所以父层作用域是引用不了子层作用域的变量的,除非将内部作用域的变量映射出来(如使用return返回,或闭包),外部才可使用。
Python有一个特长:专心地声明变量。无论外面的变量叫啥,只要你想在自己的作用域声明一个变量,即使这个变量和外部的变量重名,自己的变量还是自己的变量。如:
python 代码:a = 1
def f():
a = 2
print(a)
f() # 2
b = 3
class Demo:
b = 4
print(b) # 4
上方这个例子说明,内部作用域是可以通过声明来达到隐藏外部作用域变量名称的。那么如果我们要使用外部作用域的名称,我们该如何做呢?Python为我们提供了两个关键字来引用不同类型下外部作用域的名称。
Global关键字
global关键字用于在函数内部声明一个变量为全局变量。当在函数内部使用变量时,默认情况下,该变量是局部变量,只在函数内部有效。如果想要在函数内部修改全局变量或者访问全局变量,就需要使用global关键字。
python 代码:a = 1
def f():
a = 2
print(a) # 2
f()
def g():
global a
print(a) # 1
a = 3
print(a) # 3
g()
print(a) # 3
nonlocal关键字
nonlocal关键字用于在嵌套函数中声明一个变量为非局部变量。当在嵌套函数中使用变量时,默认情况下,该变量是局部变量,只在当前函数内有效。如果想要在嵌套函数内修改上一级函数的局部变量,就需要使用nonlocal关键字。nonlocal关键字只能用于嵌套函数中,不能用于全局作用域中。而且,nonlocal只能用于嵌套函数的上一级函数的局部变量,无法跨越多层嵌套。
python 代码:def outer():
a = 1
def inner():
nonlocal a
a = 2
inner()
print(a)
outer() # 2
在嵌套中使用global关键字
在嵌套的作用域中,可以使用global
关键字声明一个变量为全局变量。当在嵌套函数中使用global
关键字时,它会将变量绑定到最近的全局作用域。
a = 1
def f():
a = 2
def g():
global a
a = 3
g()
f()
print(a) # 3
临时作用域
临时作用域是在某些特定情况下创建的临时命名空间。例如,在eval()
或exec()
函数中执行的代码会在临时作用域中执行。
a = 1
code = '''
a = 2
print(a)
'''
exec(code) # 2