经常搞不清楚Python的命名空间和作用域,查阅了一些网上的资料,并自行做了一些测试,将结果整理成本笔记。
命名空间是从名称到对象的映射,Python大部分的命名空间都是通过字典来实现的,它的键就是变量名,它的值就是那些变量的值,核心作用是避免名字冲突。
locals()
查看局部命名空间globals()
查看全局命名空间abs()
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。
g_count = 0 # 全局作用域
def outer():
o_count = 1 # 闭包函数外的函数中
def inner():
i_count = 2 # 局部作用域
- 定义:
- 全局变量:所有函数之外定义的变量
- 局部变量:函数内部定义的变量,或者类、模块里的变量
函数内部的变量名如果第一次出现,且出现在=
前面,即被视为定义了一个局部变量,不管全局域中有没有该变量名,函数中使用的将是局部变量。从下方的示例中可以看到,在函数内部无法修改全局变量值:
num = 1 # 全局变量
def fun1():
num = 123 # 局部变量
print(num) # 输出结果 123
fun1()
123
以下示例为嵌套作用域,同样,局部作用域无法修改嵌套作用域中变量:
def outer():
num = 10
def inner():
num = 100
print(f'inner print:{num}')
print(f'inner locals:{locals()}')
inner()
print(f'outer print:{num}')
print(f'outer locals:{locals()}')
outer()
inner print:100
inner locals:{'num': 100}
outer print:10
outer locals:{'num': 10, 'inner': .inner at 0x000002CED4813820>}
global
和nonlocal
关键词当内部作用域想修改外部作用域的变量时用到。
global
:修改全局变量nonlocal
:修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量以下示例通过global
关键字声明,修改全局变量:
"""
以下实例修改全局变量num
"""
num = 1
def fun1():
global num # 需要使用 global 关键字声明,如无名为num的全局变量,则重新定义
print(num) # 输出结果 1
num = 123
print(num) # 输出结果 123
fun1()
1
123
输出结果123,说明修改了全局变量:
print(num)
123
以下示例通过nonlocal
关键字声明,修改嵌套作用域变量:
"""
以下实例修改嵌套作用域变量num
"""
def outer():
num = 10
def inner():
nonlocal num # nonlocal关键字声明
num = 100
print(num)
inner()
print(num)
outer()
100
100
定义test_module.py
, 其中将a
赋值为3
。如下命令可以在notebook中查看.py
文件:
# %load test_module.py
a = 3
模块.变量
访问,包括读写:# 导入模块
import test_module
def f1():
test_module.a = 5
print(test_module.a)
3
f1()
执行f1()
后,模块变量a
的值被成功修改
# 执行`f1()`后,模块变量`a`的值被成功修改
print(test_module.a)
5
在嵌套函数内,也可以读写导入模块的变量:
def f2():
def f22():
print(test_module.a)
f22()
f2()
5
def f2():
def f22():
test_module.a = 6
print(test_module.a)
f22()
f2()
6
print(test_module.a)
6
import
导入模块,多次执行, 实际只执行第一次,可以看到a
的值没有变化import test_module # 再次执行导入模块,不会再执行了
print(test_module.a)
6
reload
重新加载后,a
的值重置为3
from importlib import reload
reload(test_module) # reload 重新真正运行模块
print(test_module.a)
3
def f3():
import test_module
print(test_module.a)
f3()
3
print(test_module.a)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Input In [3], in ()
----> 1 print(test_module.a)
NameError: name 'test_module' is not defined
|
b = 8
def f4():
print(b) # 第一次使用 b 是 读取,是全局变量
f4()
8
print(b)
8
def f5():
b = 9 # 第一次使用 b 是 赋值,是函数局部变量
f5()
print(b)
8
def f5():
global b # 强制全局变量
b = 9
f5()
print(b)
9
• 参考资料:
o Python3 命名空间和作用域 | 菜鸟教程
o python进阶之命名空间与作用域 - 金色旭光 - 博客园
o python 归纳 (六)_模块变量作用域 - sunzebo - 博客园