从Python解释器开始执行之后,就在内存中开辟了一个空间。
每当遇到一个变量的时候,就把变量名和值的对应关系记录下来。
但是当遇到函数定义的时候解释器只是象征性地将函数名读入内存,表示知道这个函数的存在了,至于函数内部的变量和逻辑,解释器不关心的。
等执行到函数调用的时候,Python解释器会再开辟一块内存来存储这个函数的内容,这个时候,才关注函数里面有哪些东西,而函数中的变量会存储在新开辟出来的内存中。函数中的变量只能在函数的内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。
那么,这个“存放名字和值的关系”的空间起了一个名字——名字空间。
代码在运行开始的时候,创建的命名空间叫全局命名空间,在函数运行中开辟的临时空间叫局部命名空间。
命令空间和作用域:
内置命名空间:
1)Python解释器一启动就可以使用的名字存储在内置命名空间中的。
2)内置的名字在启动解释器的时候被加载到内存里。
全局命名空间:
1)是在程序从上到下被执行的过程中依次加载进内存的。
2)放置了我们设置的所有变量名和函数名。
局部命名空间:
1)就是函数内部定义的名字。
2)当调用函数的时候,才会产生这个名字的命名空间。
内置命名空间:Python解释器
全局命名空间:我们写的代码,但不包括函数中的代码
局部命名空间:函数
在局部:可以使用全局、内置命名空间的名字。
在全局:可以使用内置命名空间的名字,但是不能使用局部命名空间的名字。
在内置:不可以使用局部和全局明空的名字的。
def func()
a = 1
func()
print(a) # 在全局是不能调到a的值
加载顺序:
内置命名空间(在程序运行前加载)、全局命名空间(程序运行中,从上到下加载)、局部命名空间(程序运行中,调用才会加载)
取值:
在局部调用:局部命名空间->全局命名空间->内置命名空间
在全局调用:全局命名空间->内置命名空间
示例1:
x = 1
def func(x):
print(x)
func(10)
print(x)
结果:
1)正常情况下,直接使用内置的名字;
2)当我们在全局定义了和内置名字空间中同名的名字的时候,会使用全局的名字;
3)当当前命名空间有的话,就不再找上一级要了;
4)如果当前命名空间没有,就找上一级要,上一级没有,就再找上一级,如果内置的命名空间没有,就直接报错;
5)多个函数应该拥有多个独立的局部名字空间,不相互干扰。
作用域:就是作用范围。
全局作用域:包含了内置命名空间、全局命名空间,在整个文件的任意位置都能被引用、全局有效。
局部作用域:局部命名空间,只能在局部范围内生效。
global 关键字:
a = 1
def func():
global a # 声明全局变量
a += 1
func()
func()
print(a)
说明:对于不可变数据类型,在局部作用域可以查看到全局作用域中的变量。
但是不能直接修改,如果需要修改,需要在程序的开头添加global声明。
如果在局部函数内声明了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效。
我们看下globals()和locals(),两个方法:
a = 1
b = 2
def func():
x = "aaa"
y = "bbb"
print(locals())
func()
print(globals())
结果:
C:\CodeProjects\PythonProjects\s9\venv\Scripts\python.exe C:\CodeProjects\PythonProjects\s9\day2\01homework.py
{'x': 'aaa', 'y': 'bbb'}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000024764E1FF70>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:\\CodeProjects\\PythonProjects\\s9\\day2\\01homework.py', '__cached__': None, 'a': 1, 'b': 2, 'func': <function func at 0x0000024764DB3E20>}
进程已结束,退出代码0
在实践中,尽量少使用global关键字。
对全局变量要尽量少用,或者不用。