1. 名称空间与作用域的概念
在学习 Python 的时候,我们经常会听到「名称空间」和「作用域」这两个概念。它们是 Python 编程语言中非常重要的一部分,对于理解 Python 中的变量、函数和模块等概念有着至关重要的作用。
名称空间,简单来说,就是一个存储名称与值的映射关系的字典,用于存储变量、函数和其他对象。
在 Python 中,每个名称空间都有一个唯一的名称标识符,并按照不同的可访问范围分成了不同的类型,但这些名称空间并不会直接接触。下面我们将一一介绍 Python 中的各种名称空间。
作用域,指的是在程序中访问变量、函数等对象的有效区域。Python 中存在四种作用域:内置作用域(built-in)、全局作用域(global)、局部作用域(local)和非局部作用域(nonlocal)。
2. Python 中的名称空间
2.1 内置名称空间
Python 解释器已经定义了一些内置名称空间的变量和函数。这些内置名称空间的变量和函数是可以在程序的任何地方访问的,不需要导入任何模块。例如:
print("Hello World!")
在上面的代码中,我们使用了内置变量 print。这个变量存储了一个可以输出文本到屏幕的函数,“Hello World!” 就是它输出的内容。
2.2 全局名称空间
全局名称空间用于存储全局变量和函数,它存在于整个程序的运行过程中,也就是说,它在程序启动时被创建,程序结束时被删除。在程序中定义的变量和函数都是全局名称空间的一部分。
当在函数内部访问全局变量时,需要使用 global 关键字,以便告诉 Python 编译器变量是一个全局变量。
# 定义全局变量 x
x = 10
def func():
# 声明 x 是全局变量
global x
# 修改全局变量 x
x = 20
func()
print(x)
上面的代码中,我们定义了一个全局变量 x,并在函数内部将其修改为 20。由于使用了 global 关键字,所以在函数内部修改全局变量 x 后,在函数外部打印 x 的值时,会输出 20。
2.3 局部名称空间
局部名称空间用于存储函数内部的变量和函数。它只在函数内部有效,在函数调用结束时被删除。在函数内部定义的变量和函数都是局部名称空间的一部分。
def func():
# 定义局部变量 x
x = 10
print(x)
func()
# NameError,x 在外部的代码中没有定义
print(x)
上面的代码中,我们定义了一个函数 func,在函数内部定义了一个局部变量 x,函数执行完毕后,局部变量 x 被删除。在函数外部,我们尝试打印变量 x,但是因为变量 x 只存在于函数内部,所以会报 NameError 的错误。
2.4 内置函数 locals() 和 globals()
我们可以使用内置函数 locals() 和 globals() 查看当前作用域的名称空间。
locals() 用于返回当前作用域的局部名称空间,返回值为字典类型。
def func():
x = 10
print(locals())
func()
# {'x': 10}
globals() 用于返回当前作用域的全局名称空间,返回值为字典类型。
x = 10
def func():
print(globals())
func()
# {..., 'x': 10, ...}
3. Python 中的作用域
3.1 内置作用域
内置作用域是包含了 Python 内置函数和变量的名称空间。
# 查看内置作用域的名称
print(dir(__builtins__))
3.2 全局作用域
全局作用域指的是在全局范围内定义的变量和函数所在的名称空间。
# 定义全局变量 x
x = 10
def func():
# 使用全局变量 x
print(x)
func() # 10
3.3 局部作用域
局部作用域指的是在函数内部定义的变量和函数所在的名称空间。
def func():
# 定义局部变量 x
x = 10
print(x)
func() # 10
3.4 非局部作用域
非局部作用域是指那些不是在全局和函数内部定义的作用域,通常是闭包和嵌套函数。
def func1():
x = 1
def func2():
# 声明 x 不是局部变量
nonlocal x
x += 1
print(x)
func2()
func1() # 2
在上面的代码中,我们定义了两个函数 func1 和 func2,其中 func2 是 func1 的内部函数。由于在 func2 中使用了变量 x,我们使用 nonlocal 关键字告诉 Python 编译器 x 不是 func2 的局部变量,而是 func1 中的变量 x。
4. 总结
名称空间和作用域是 Python 编程中重要的概念,理解其含义和使用方法非常关键。在编写程序时,我们需要注意命名规范,尽量避免名称的冲突,以避免不必要的错误。