1、命名空间
namespace (命名空间)是一个从名字到对象的映射,大部分命名空间当前都由 Python 字典实现。
(1)Python 中命名空间分类:
- 内置命名空间(Built-in Namespace):包含 Python 解释器自带的函数和变量名,可以使用 dir(__builtins__) 查看并使用这些函数和变量。
- 全局命名空间(Global Namespace):定义在脚本或模块层级的命名空间,可以在全局范围内使用。全局命名空间可以通过 globals() 查看。
- 局部命名空间(Local Namespace):定义在函数或类中的命名空间,在函数或类内部可以使用。每次函数调用都会创建一个新的局部命名空间,函数调用结束后局部命名空间会被销毁。
(2)Python中命名空间的生命周期:
- 内置命名空间:Python解释器启动时自动创建,直到解释器关闭才会销毁。
- 全局命名空间:模块被导入时创建,模块被解释器清除时销毁。
- 局部命名空间:调用该函数时创建,并在函数返回或抛出不在函数内部处理的错误时被删除。 (实际上,用“遗忘”来描述实际发生的情况会更好一些。) 当然,每次递归调用都会有自己的本地命名空间。
2、作用域
作用域(scope)是一个命名空间可直接访问的 Python 程序的文本区域。说人话就是,Python作用域指的是变量的生命周期以及其可被访问的范围。
(1)Python 作用域分类:
- 内置作用域(built-in):Python解释器内置的函数和变量,在任何地方都可以使用。
- 全局作用域(global):定义在函数外部的变量拥有全局作用域,意味着它们可以在模块的任何地方被访问。
- 局部作用域(local):定义在函数内部的变量拥有局部作用域,意味着它们只能在函数内被访问。
- 嵌套作用域(enclosed):在嵌套函数中,内层函数可以访问外层函数的变量,但是不包括全局作用域中的变量。
(2)Python作用域的生命周期:
- 内置作用域是永久的,会在解释器启动时自动加载;
- 全局作用域在程序开始时创建,并在程序结束时销毁;
- 局部作用域在函数被调用时创建,并在函数执行完毕后销毁;
- 非局部作用域是一个函数内嵌套函数时的作用域,变量可在内层函数和外层函数间共享,当外层函数执行完毕后,非局部作用域也会被销毁。
(3)Python中命名空间和作用域的区别:
- Python中,命名空间是一个包含标识符和它们的值之间的关系的映射表,是一个字典。而作用域表示一个标识符可见或可访问的区域。
3、变量
在Python中,变量是用于存储数据的标识符。它们用于给数据赋予一个名称,并且可以在程序中随时引用和修改这些数据。
当我们创建一个变量时,实际上是在内存中分配了一块空间来存储数据,并且将变量名与这块内存空间关联起来。这样,我们可以通过变量名来访问和操作存储在内存中的数据。
(1)创建变量:
变量的创建非常简单,只需要使用等号(=)将变量名和对应的值进行赋值操作。
例如:
x = 5 # 将数字 5 赋值给变量 x
name = "Alice" # 将字符串 "Alice" 赋值给变量 name
is_sunny = True # 将布尔值 True 赋值给变量 is_sunny
注意,可以使用逗号分隔多个变量,并将它们分别赋予相应的值:
x, y, z = 1, 2, 3 # 将整数 1、2、3 分别赋值给变量 x、y、z
name, age = "Bob", 25 # 将字符串 "Bob" 和整数 25 分别赋值给变量 name、age
(2)变量命名规则:
- 变量名只能包含字母、数字和下划线(_),不能以数字开头。
- 变量名区分大小写,例如 a 和 A 是两个不同的变量。
- 避免使用Python 的关键字(如 if、else、while 等)作为变量名。
- 变量名应具有描述性,以提高代码可读性。
(3)调用变量:
使用变量时只需要调用其名称即可。例如,以下代码会打印出变量 x 的值:
print(x)
(4)删除变量:
使用del语句可以删除一个变量及其对应的值,例如:
x = 5
del x # 删除变量 x
4、全局变量和局部变量
Python 中根据作用域的不同可以把变量分为全局变量和局部变量,变量的作用域在定义时就被固定了。
详见:Global and Local Variables in Python - GeeksforGeeks
(1)变量的分类:
- 全局变量(global variable):定义在函数或类外部,作用域为整个模块,可被模块内的所有函数和方法访问。
- 局部变量(local variable):定义在函数或类内部,作用域只限于当前函数或方法内部,外部无法访问。
- 非局部变量(nonlocal variable):局部变量的一种,定义在嵌套函数中,且被内函数引用的变量,需要使用nonlocal关键字。
(2)变量的生命周期:
- 当变量被创建时,它进入当前所处作用域;
- 在作用域内,变量可以被使用,更新或删除;
- 变量在离开作用域时被销毁。
(3)变量的查找顺序(LEGB):
- 遵循LEGB原则,Python解释器会从当前作用域开始查找这个变量,按照局部作用域>>嵌套作用域>>全局作用域>>内置作用域的顺序查找。如果查找到最外层的内置作用域也找不到,Python将引发一个NameError异常。
例子如下:
x = 10 # global variable
def func():
y = 5 # local variable
print(x, y)
func() # 输出:10 5
print(y) # 报错,因为 y 是一个局部变量,不在全局范围内
5、访问外部变量
正常情况下,在函数内是可以直接访问外部变量的(注意,这里的外部变量指的是全局变量和外层的局部变量,这些变量将是只读的,不可以修改它们。这个时候只会在内部函数的作用域中创建一个新的局部变量,而同名的外部变量保持不变)。如果想要进行赋值和修改这些外部变量,我们需要用到关键字 `global` 或 `nonlocal` 。
(1)直接访问外部变量
a = 10 # global variable
# Accessing global Variable From Inside a Function
def test_scope():
b = a + 10
print(b)
# calling a function
test_scope()
输出:20
说明: 在函数test_scope中直接访问了外部变量a(全局变量),表达式"b = a+10",左侧的b是局部变量,右侧的a是外部变量a。
(2)不可以直接修改外部变量
a = 10 # global variable
# Modifying Global Variable From Inside the Function
def test_scope():
a = a + 10
print(a)
# calling a function
test_scope()
输出报错信息:
UnboundLocalError: local variable 'a' referenced before assignment
说明: 在函数test_scope中,表达式"a = a+10",左侧的a是全局变量,右侧的a是局部变量,在给左侧的全局变量a赋值的时候没有初始化右侧局部变量a的值,所以报错了。
6、global关键字
使用 global关键字来访问全局变量。详见:Global keyword in Python - GeeksforGeeks
a = 10 # global variable
# Modifying Global Variable From Inside the Function
def test_scope():
global a
a = a + 10
print(a)
# calling a function
test_scope()
输出:20
说明: 在函数test_scope中,添加一行代码 global a实现在函数内部将变量a声明为全局变量a,初始值为10。
7、nonlocal关键字
使用 nonlocal关键字访问局部变量。详见:Python nonlocal Keyword - GeeksforGeeks
def outer():
a = 100 # Our local variable
def inner():
nonlocal a # Reference a in the upper scope
a = 200 # Overwrite this variable
print(a)
inner() # Calling inner function
print(a) # Printing local variable
# Calling outer function
outer()
输出:
200
200
说明:内函数inner中,nonlocal a将这里的局部变量标记为上层作用域outer函数中的局部变量a = 100,并将值修改为200。
reference:
Python作用域和命名空间 — Python 3.8.16 文档
Global and Local Variables in Python - GeeksforGeeks
Global keyword in Python - GeeksforGeeks