命名空间按字面意思就是存储名字的一段空间,那么什么是名字呢?变量由变量名,函数有函数名,类有类名等等这些都是名字。在python中,命名空间分为三种:局部命名空间、全局命名空间,内置命名空间。
内置命名空间:变量的使用需要先定义后使用,但是我们在打开python解释器的时候,我们直接就可以使用一些内置函数,解释器已经帮我们定义了,直接使用就好了。
全局命名空间:在我看来,在一个python文件中,顶格写的是全局变量,而全局变量名称存放在全局命名空间里。
局部命名空间:在函数或者类中定义的变量或者属性名称存放在局部命名空间中。
作用域分为全局作用域和局部作用域。在内置名称空间和全局名称空间中存放的名称均为全局作用域。而在局部命名空间中的名称为局部作用域。局部作用域只能在局部中使用,而全局作用域,可以在全局中使用。
如上面的程序,使用globals()查看全局名称空间时只有如下名字x,Gaven,func,g1
可以如下理解
在全局命名空间中有四个名称x、func、Garen、G1。在func和Garen以及 G1中有自己的名字空间,也就是有局部变量或者属性。里面的这些函数以及变量不能再全局作用域中使用。下面我们具体来看一下类的属性引用。
类的属性分为两种:特征和方法。特征代表类的一些状态,方法代表类的技能。比如上图中的盖伦类,德玛西亚代表盖伦的阵营,attack代表盖伦的技能。类创造出来了,那么如何使用类呢?有两种方法:1. 创建实例 2. 直接使用类的属性。如下:
g1 = Garen('666')
g1.camp
Garen.camp
两种类的使用方法都需要使用到。‘.’代表属性的引用。可以这样理解,一个Garen相当于机哆啦A梦的万能袋子,在外面看不到,如果需要使用,需要从袋子里掏出工具来。下面具体分析下两种类的属性引用。实例化
g1 = Garen('666')
使用g1.__dict__()可以打印出g1的名字空间,如下图所示
从图中可以看出,g1的名字空间只用init函数中的一些变量,但是g1可以使用类的属性和方法,那么为什么g1的名字空间没有这些变量的名称?其实g1的产生可以分为三部分。一是自身的一些变量。__init__()函数中的变量;那么不在这个命名空间中的变量g怎么引用到了呢?其实很简单,当g1区类中引用camp时,发现g1的命名空间中并不存在camp这个变量,那么就会去全局变量中找值。这里的全局比阿娘就是Garen的变量。从另外一个方面讲,所有由Garen创造出来的实例,引用Garen的变量(数据)都是指向Garen的变量。所以有下面等式:
id(g1.camp)=id(g2.camp)=id(g3.camp)
其中g1、g2、g3都是有Garen创造出来的实例
最后一部分是g1如何引用到类的方法呢?g1的名字空间总没有函数名称,之所以能引用到函数,是因为这些函数都绑定到了g1实例上。所以有下面的等式
id(g1.attack)!=id(g2.attack)!=id(g3.attack)
也可以这样理解
g1 = Garen('666'),其实是在进行Garen.__init__(g1.'666'),其中self为g1,后面的函数自动将self用g1lai 代替,从而进行方法绑定到实例。
2. 类的引用
Student.__dict__有如下显示
上图的显示和类中的locals显示差不多,都是类的属性:变量和函数(一定叫函数,方法是实例叫的),所以直接使用Student.camp、Student.attack()即可