Python名称空间与作用域
什么是名称空间?
比如下图的长方形代表内存,在这个内存里我要设置一个变量100,那么这个变量得有个门牌号,就叫他a吧,但其实变量不是这么存储的,他其实的存储方式是这样的,他会有一个名称空间,这个名称空间里面有一个表,他这个表里的内容是变量的名对应变量的内存地址这么一个关系,那么你定义一个变量b,那b也会有相应的内存地址,只要你定义变量,名称空间里就会多一组变量名对应他相应的内存地址,你定义以后,他会通过变量内存地址去找你相应的变量的值,他是这么存储的。
就是门牌号对应相应的内存地址。
对于这个表来说,他就是名称空间,也就说名称空间是存储变量名于他相对应的内存地址的关系的一个表。
什么是作用域?
Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。
函数定义了本地作用域,而模块定义的是全局作用域。
如果想要在函数内定义全局作用域,需要加上global修饰符。
名称空间又分为三种:
内置名称空间:python自带的,启动时就有的。如print、max、min。(ctrl+左键可以看到内置函数的代码)
全局名称空间:顶格写的变量。调用的时候才会产生全局名称空间。
局部:函数体内定义的变量
这三种有什么区别呢?
内置:print是python 的内置函数,函数即变量,那么我们定义一个函数,也就产生了相应的名称空间。print也是一个变量的名字,那么他内置的方法就是他的值(他的方法无非就是打印),他实现的方法也是用代码写出来的,来看一下print里面的代码,选中print,CTRL+鼠标左键。
全局:比如定格写的a = 10,我只要run,那么名称空间里就会有这个变量与他变量值的内存地址对应的关系。整个py文件他都是有效的。
不管是在函数体内调用这个a,还是别处调用,只要是这个py文件,我都能找的到这个变量a。
再看一下这个:
虽然a=5没有定格写,但是他只是做了条件判断,那么这个a也是属于全局名称空间。
局部:函数体内定义的变量
我们可以看到,我在外部调用的时候是找不到变量a的,由此可以得出,函数体内定义变量,是局部名称空间。
所以说print就是一个变量,他的方法就是他的value,所以像python自带的函数,就是内置名称空间。
什么时候有名称空间
在调用定义的变量的时候才有名称空间
python名称空间加载顺序
我们看一下下面这个函数
我们要知道,pyhton执行代码是从上往下执行的,当我一运行这个函数,python解释器知道它函数了,它会去找可执行的代码,因此,这个函数体内代码会被略过,pyhton解释器找到f1(),知道这调用函数f1,它会在返回f1函数体内,它又找到了a=10,并且打印变量a,那么我们在调函数f1的时候产生了局部名称空间,那么我们定义的函数f2呢,它产生了名称空间吗?答案很简单,是没有的,因为函数f2并没有被调用。那么我想调用函数f2怎么调用呢?
这就涉及到了名称空间的访问顺序
内置 全局 局部
看一下这个函数,我指调用了函数f1,它并没报错,调用f2也不会报错,只有调用f3的时候才会报错,因为f3函数体内打印x。而我并没有定义变量x,函数体内的变量产生的局部名称空间,因此,f3调用的变量x不会影响到函数f1和函数f2.
由此可得出名称空间的加载顺序,python解释器一运行,首先加载的内置的,内置不加载的话,函数f1我们就调用不到了,更不用等到调用函数f3出错的时候,其次加载的是全局,我们再函数外部定义x=1的话,那么它会调用这个变量x=1。
最后才运行局部的,我们再在函数f1体内定义一个x=3,那么它会去调用这个x=3。
python名称空间访问顺序
局部 全局 内置
首先来说,我们调用函数f3的时候,它会先找函数f3体内定义的变量x=4,如果它没找到,它会再去找x=3,如果还没找到,再去找x=2,还是没有的话,再找到x=1。