全局空间和部分空间
命名空间
命名空间的概念的提出是为了划分和控制变量是否可见,以及生存周期的长短;命名空间的作用范畴叫做作用域。
划分一块区域保留所有数据,以字典的形式存储(变量与值造成映射关系)。一共三种。
-
内建命名空间:
- 解释器启动时创立,直到解释器运行完结,生存周期最长;
-
全局命名空间:
- 文件运行时创立,直到解释器运行完结,生存周期较长;
-
部分命名空间:
- 数调用时,外面的局部变量才创立,调用完结后即开释,生存周期较短;
创立和销毁程序
-
创立程序:
- python 解释器启动 -> 创立内建命名空间 -> 创立全局命名空间 -> 创立部分命名空间
-
销毁程序:
- 函数调用完结后 -> 销毁函数对应的部分命名空间数据 -> 销毁全局命名空间数据 -> 销毁内建命名空间数据
全局变量和局部变量
什么是全局和局部变量
局部变量就是在函数外部定义的变量,局部变量所在的就是部分命名空间,作用域仅仅在函数外部可见,也就是说只能在函数外部应用。
# 在函数中创立的变量就是局部变量
def func():
var = '局部变量'
# 局部变量不能够在非对应部分环境中应用
print(var) # error, 该变量不存在
全局变量就是在函数内部定义的或者应用 global
在函数外部定义的变量,全局变量所在的命名空间就是全局命名空间,作用域横跨整个文件,就是说在整个文件中的任何一个中央都能够应用全局变量。
# 在全局环境中创立的变量就是全局变量
var = '全局变量'
def func():
# 在部分中也能够应用全局变量
print(var) # 全局变量
func()
局部变量最好不要和全局变量同名,如果同名,在部分环境中就无奈应用全局变量了。
var = '全局变量'
def func():
# 先应用了全局变量
print(var) # error, 找不到该变量
# 而后局部变量和全局变量同名,那么新的局部变量就会在部分空间中笼罩了全局变量的所有影响力,这就叫做局部变量批改了全局变量;# 这样的话导致在部分空间中无奈在应用该全局变量,之前在部分空间中应用的该变量就成为了先调用后定义;导致出错。var = '局部变量'
print(var)
func()
# 然而部分同名变量不会影响到全局变量的值
print(var) # 全局变量
内置函数就是内建命名空间,指的是那些 python 中自带的、内置的函数。
作用域
局部变量作用域:在函数的外部
全局变量作用域:横跨整个文件
生命周期
内置变量 -> 全局变量 -> 局部变量
内置变量自 python 程序运行的时候开始,始终等到 python 程序完结之后才会开释;
全局变量自创立开始,始终到程序完结或者被革除才会开释;
局部变量字创立开始,始终到部分空间执行完结或者革除就会开释;
全部分函数和关键字的应用
函数
函数 | 作用 |
---|---|
globals() | 寄存着全局作用域中的所有内容,以字典的模式返回 |
locals() | 寄存着以后作用域中的所有内容,以字典的模式返回 |
globals()
返回所有的全局作用域中的内容。
如果在全局,调用 globals 之后,获取的是打印之前的所有变量,返回字典,全局空间作用域;
# 定义一些全局变量
a, b, c = 1, 2, 3
# 调用 globals 函数
res = globals()
# 第一次打印,蕴含 a b c
print(res)
'''
后果:{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002DBDCA5D198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'res': {...}}
'''
# 再定义一些变量
d, e, f = 1, 2, 3
# 第二次打印,蕴含 a b c d e f
print(res)
'''
后果:{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002DBDCA5D198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'res': {...}, 'd': 1, 'e': 2, 'f': 3}
'''
如果在部分,调用 globals 之后,获取的是调用之前的所用变量,返回字典,全局空间作用域;
# 定义一些全局变量
a, b, c = 1, 2, 3
# 在部分环境中应用 globals 函数
def func():
res = globals()
print(res)
# 调用函数
func()
'''
后果:不蕴含 d e f
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001E7C287D198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'func': <function func at 0x000001E7C2772F28>}
'''
# 再定义一些全局变量
d, e, f = 4, 5, 6
# 第二次调用函数
func()
'''
后果:蕴含 d e f
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000021A3F3DD198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'func': <function func at 0x0000021A3F2D2F28>, 'd': 4, 'e': 5, 'f': 6}
'''
globals 能够动态创建全局变量
dic = globals()
print(dic) # 返回零碎的字典
'''
后果:{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000026F357ED198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'dic': {...}}
'''
# 在全局的字典当中,通过增加键值对,主动创立全局变量,对应的键是变量名,对应的值是变量指向的值
dic['msr123123123'] = '123456'
print(msr123123123) # 123456
# 查看全局内容
print(dic)
'''
后果:{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000161D944D198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test6.py', '__cached__': None, 'dic': {...}, 'msr123123123': '123456'}
'''
locals()
返回以后所在作用域的所有内容。
如果在全局,调用 locals 之后,获取的是打印之前的所有变量,返回字典,全局空间作用域;
# 定义一些全局变量
a, b, c = 1, 2, 3
# 调用 locals 函数
res = locals()
# 第一次打印,蕴含 a b c
print(res)
'''
后果:{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000018C82A3D198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test1.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'res': {...}}
'''
# 再定义一些变量
d, e, f = 1, 2, 3
# 第二次打印,蕴含 a b c d e f
print(res)
'''
后果:{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000018C82A3D198>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/0-project/python/mymsr/ceshi/test1.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'res': {...}, 'd': 1, 'e': 2, 'f': 3}
'''
如果在部分,调用 locals 之后,获取的是调用之前的所有变量,返回字典,部分空间作用域;
# 定义一些局部变量
def func():
# 局部变量
aa, bb, cc = 11, 22, 33
# 第一遍调用
res = locals()
# 第一次打印,蕴含 aa bb cc
print(res) # {'cc': 33, 'bb': 22, 'aa': 11}
# 再定义一些局部变量
dd, ee, ff = 44, 55, 66
# 第二次打印,不蕴含 dd ee ff
print(res) # {'cc': 33, 'bb': 22, 'aa': 11}
# 调用第二遍
res2 = locals()
# 打印第一次的调用,蕴含 dd ee ff
print(res) # {'cc': 33, 'bb': 22, 'aa': 11, 'ff': 66, 'ee': 55, 'dd': 44, 'res': {...}}
# 打印第二次的调用,蕴含 dd ee ff
print(res2) # {'cc': 33, 'bb': 22, 'aa': 11, 'ff': 66, 'ee': 55, 'dd': 44, 'res': {...}}
# 调用函数,返回在函数中的局部变量
func()
关键字
关键字 | 作用 |
---|---|
global | 申明全局变量、获取应用和批改全局变量的权限 |
nonlocal | 批改局部变量(以后函数的上一层的局部变量) |
global
在部分环境中创立的变量是局部变量,在全局环境中是不能够应用的。然而应用 global 定义的变量就是一个全局变量,这个变量能够全局环境中应用。
def func():
var = '局部变量'
global glvar
glvar = '全局变量'
# 肯定要执行部分环境哟
func()
# 全局环境中
print(var) # error,局部变量不能调用
# 应用 global 定义的变量是全局变量
print(glvar) # 全局变量
在部分环境中无奈批改全局变量的值,应用 global 能够在部分环境中批改全局变量。
var = '全局变量'
def func():
global var
var = '部分环境中批改'
func()
print(var) # 部分环境中批改
函数的嵌套
在学习 nonlocal 之前咱们须要先学习一些对于函数嵌套的常识。
内函数和外函数
函数之间是能够相互嵌套的,外层的叫做外函数,内层的叫做内函数。
def outer():
print('我叫 outer,是外函数')
def inner():
print('我叫 inner,在 outer 的外面,是内函数')
# 在外函数中执行内函数
inner()
# 执行外函数
outer()
'''
后果:我叫 outer,是外函数
我叫 inner,在 outer 的外面,是内函数
'''
- 内函数不能够间接在外函数外执行调用
- 调用外函数后,内函数也不能够在函数内部调用
- 内函数只能够在外函数的外部调用
- 内函数在外函数外部调用时,有先后顺序,必须先定义在调用,因为 python 没有预读机制,这个预读机制实用于 python 中的所有场景。
# 外层是 outer,内层是 inner,最里层是 smaller,调用 smaller 里的所有代码
def outer():
print('我叫 outer,是最外层函数,是 inner 和 smaller 的外函数')
def inner():
print('我叫 inner,是 outer 的内函数,是 smaller 的外函数')
def smaller():
print('我叫 smaller,是 outer 和 inner 的内函数')
# 先在 inner 中执行 smaller
smaller()
# 而后在 outer 中执行 inner
inner()
# 最初再执行 outer 能力执行 smaller 函数
outer()
'''
后果:我叫 outer,是最外层函数,是 inner 和 smaller 的外函数
我叫 inner,是 outer 的内函数,是 smaller 的外函数
我叫 smaller,是 outer 和 inner 的内函数
'''
咱们在多个函数嵌套的时候要留神,不论外函数还是内函数,都是函数,只有是函数中的变量都是局部变量。
外延能够应用外函数的局部变量,外函数不能间接应用内函数的局部变量。
LEGB 准则
LEGB 准则就是一个就近找变量准则,根据就近准则,从下往上,从里向外,顺次寻找。
B————Builtin(Python):Python 内置模块的命名空间(内建作用域)G————Global(module):函数内部所在的命名空间(全局作用域)E————Enclosing Function Locals:内部嵌套函数的作用域(嵌套作用域)L————Local(Function):以后函数内的作用域(部分作用域)
nonlocal
当初咱们正式学习 nonlocal 关键字,nonlocal 的作用是批改以后部分环境中上一层的局部变量。那么咱们依据这个作用便晓得了 nonlocal 的应用环境至多是一个二级的嵌套环境,且外层的部分环境中必须存在一个局部变量。
def outer():
# 定义变量
lvar = 'outer var'
def inner():
# 内函数应用 nonlocal 批改上一层的局部变量
nonlocal lvar
lvar = 'inner var'
# 执行 inner 函数
inner()
print(lvar)
outer() # inner var
如果上一层的部分环境中没有这个变量怎么办,那么就依据 LEGB 准则向上寻找。
def outer():
# 定义变量
lvar = 'outer var'
def inner():
def smaller():
# smaller 中批改变量,然而 inner 中没有,就向上寻找批改 outer 中的变量
nonlocal lvar
lvar = 'smaller var'
# 执行 smaller 函数
smaller()
# 执行 inner 函数
inner()
print(lvar)
# 执行 outer 函数
outer()
如果层层寻找,直到最外层的函数中也没有这个变量,那么就会报错,因为 nonlocal 只会批改局部变量,如果超出范围,就会报错。
var = 1 # 变量在最外层的函数之外,也就是全局变量,nonlocal 无奈批改
def outer():
def inner():
def smaller():
nonlocal var # error,没有局部变量
var = 2
print(var)
smaller()
inner()
outer()
总结
全局变量和局部变量
部分环境中能够调用全局变量,然而不能批改(然而如果全局变量是可变数据则能够批改其中的值)
全局环境中不能调用局部变量 也不能批改
函数
global()
(在函数外部应用,能够对全局变量进行操作)
1、能够在部分环境中定义全局变量
2、能够在部分环境中批改全局变量
nonlocal()
(在内函数中应用,能够在内函数中批改外函数中的局部变量)
关键字
locals
1、locals 获取以后作用域当中所有的变量
如果在全局调用 locals 之后,获取的是打印之前的所有变量,返回字典,全局作用域
如果在部分调用 loclas 之后,获取的是调用之前的所有变量,返回字典,部分作用域
globals
2、globals 只获取全局空间中的所有变量
如果在全局调用 globals 之后,获取的是打印之前的所用变量,返回字典,全局作用域
如果在部分调用 globals 之后,获取的是调用之前的所用变量,返回字典,全局作用域