全局空间和局部空间
命名空间
命名空间的概念的提出是为了划分和控制变量是否可见,以及生存周期的长短;命名空间的作用范围叫做作用域。
划分一块区域保存所有数据,以字典的方式存储(变量与值形成映射关系)。一共三种。
- 内建命名空间:
- 解释器启动时创建,直到解释器运行结束,生存周期最长;
- 全局命名空间:
- 文件运行时创建,直到解释器运行结束,生存周期较长;
- 局部命名空间:
- 数调用时,里面的局部变量才创建,调用结束后即释放,生存周期较短;
创建和销毁顺序
- 创建顺序:
- python解释器启动->创建内建命名空间->创建全局命名空间->创建局部命名空间
- 销毁顺序:
- 函数调用结束后->销毁函数对应的局部命名空间数据->销毁全局命名空间数据->销毁内建命名空间数据
全局变量和局部变量
什么是全局和局部变量
局部变量就是在函数内部定义的变量,局部变量所在的就是局部命名空间,作用域仅仅在函数内部可见,也就是说只能在函数内部使用。
def func():
var = '局部变量'
print(var)
全局变量就是在函数外部定义的或者使用global 在函数内部定义的变量,全局变量所在的命名空间就是全局命名空间,作用域横跨整个文件,就是说在整个文件中的任何一个地方都可以使用全局变量。
var = '全局变量'
def func():
print(var)
func()
局部变量最好不要和全局变量同名,如果同名,在局部环境中就无法使用全局变量了。
var = '全局变量'
def func():
print(var)
var = '局部变量'
print(var)
func()
print(var)
内置函数就是内建命名空间,指的是那些python中自带的、内置的函数。
作用域
局部变量作用域:在函数的内部
全局变量作用域:横跨整个文件
生命周期
内置变量 -> 全局变量 -> 局部变量
内置变量自python程序运行的时候开始,一直等到python程序结束之后才会释放;
全局变量自创建开始,一直到程序结束或者被清除才会释放;
局部变量字创建开始,一直到局部空间执行结束或者清除就会释放;
全局部函数和关键字的使用
函数
函数 | 作用 |
---|
globals() | 存放着全局作用域中的所有内容,以字典的形式返回 | locals() | 存放着当前作用域中的所有内容,以字典的形式返回 |
globals()
返回所有的全局作用域中的内容。
如果在全局,调用globals之后,获取的是打印之前的所有变量,返回字典,全局空间作用域;
a, b, c = 1, 2, 3
res = globals()
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
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
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)
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
res = locals()
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
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()
print(res)
dd, ee, ff = 44, 55, 66
print(res)
res2 = locals()
print(res)
print(res2)
func()
关键字
关键字 | 作用 |
---|
global | 声明全局变量、获取使用和修改全局变量的权限 | nonlocal | 修改局部变量(当前函数的上一层的局部变量) |
global
在局部环境中创建的变量是局部变量,在全局环境中是不可以使用的。但是使用global定义的变量就是一个全局变量,这个变量可以全局环境中使用。
def func():
var = '局部变量'
global glvar
glvar = '全局变量'
func()
print(var)
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中的所有场景。
def outer():
print('我叫outer,是最外层函数,是inner和smaller的外函数')
def inner():
print('我叫inner,是outer的内函数,是smaller的外函数')
def smaller():
print('我叫smaller,是outer和inner的内函数')
smaller()
inner()
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 lvar
lvar = 'inner var'
inner()
print(lvar)
outer()
假如上一层的局部环境中没有这个变量怎么办,那么就根据LEGB原则向上寻找。
def outer():
lvar = 'outer var'
def inner():
def smaller():
nonlocal lvar
lvar = 'smaller var'
smaller()
inner()
print(lvar)
outer()
如果层层寻找,直到最外层的函数中也没有这个变量,那么就会报错,因为nonlocal只会修改局部变量,如果超出范围,就会报错。
var = 1
def outer():
def inner():
def smaller():
nonlocal var
var = 2
print(var)
smaller()
inner()
outer()
总结
全局变量和局部变量
局部环境中可以调用全局变量,但是不能修改(但是如果全局变量是可变数据则可以修改其中的值) 全局环境中不能调用局部变量 也不能修改
函数
global()
(在函数内部使用,可以对全局变量进行操作) 1、可以在局部环境中定义全局变量 2、可以在局部环境中修改全局变量
nonlocal()
(在内函数中使用,可以在内函数中修改外函数中的局部变量)
关键字
locals
1、locals获取当前作用域当中所有的变量 如果在全局调用locals之后,获取的是打印之前的所有变量,返回字典,全局作用域 如果在局部调用loclas之后,获取的是调用之前的所有变量,返回字典,局部作用域
globals
2、globals只获取全局空间中的所有变量 如果在全局调用globals之后,获取的是打印之前的所用变量,返回字典,全局作用域 如果在局部调用globals之后,获取的是调用之前的所用变量,返回字典,全局作用域
|