符号机制
1. 子符号的概念 名词空间:模块、类、namespace;local()、globals()、vars()
使用之前的示例代码:
在class中,a作为一个符号,只是它的A的子语句块中。我们把它视为A的子符号,也就是习惯中所说的名词空间。在右边输出中,可以看以名词空间的作用,两个同名符号,指向不同的实体。就相当于文件跟目录一样,使我们管理起来很方便。
名词空间看起来像是一个神秘的概念。其实很简单,就跟我们的目录文件一样,比如我们找F:/my/data.txt。 my就是我们的名词空间,我们可以在F:/my中起建立只属于这个文件夹的名字。
1.1 名词空间的实现
名词空间以一个map作为主体,当指定名词空间时,通过子符号快速找到子符号对应的实体。其实也就是目录文件的思路。这个最上层的目录就是globals ()返回的全局符号。同时还有一个locals()用来存储暂时使用的符号,主要用于函数定义时,一旦函数使用完,内部符号便销毁。
1.2 名词空间的引入 vars(obj)取出自定义符号__dict__ dir(obj)可以取出全部的子符号
像上面定义一个对象一样,python解释器为对象分配一大块内存块。我们可以定义任意名称(必须符合python命名限定)的符号名,不必担心任何重名问题。有时为了实现一套复杂的系统,我们需要写很多python的代码。这些代码会分布在很多文件中,我们会把通常把文件在python中当模块引使用。这些文件中的符号,我们同样会限制这些模块中的符号不会与我们当前环境中的符号重名(导致关联不到想要的实体)。这时,我们会把模块名当作这些符号的空间。
1.3 自定义名词空间
在一个大的源文件中,难免我们声明很多符号。如果面向对象的意识不够强,这些符号将全部暴露在globals()空间中,维护起来会很麻烦。我们可以自己伪造一个名词空间(就是一个map)。
注,第3行即向exec提供一个工作空间。
2. 查看符号实体关联情况 id / type / instance / issubclass / callable ...
任何一个符号可以关联到任何实体,以C语言的角度讲,符号就是一个void *。比如下图:
那么,使用者如何知道一个符号所关联的实体是什么?可以使用系统定义的一系列函数,借用 java 的思路命名方式,这里应该叫反射 (如果我 java 没学错) 。
关键注意4-7行与16-19行的比较,以及15行符号赋值导致的重新关联。5行与17行,表明两个符号关联同一个实体。
type输出更进一步说明了,一切实体都是class。第22行,表明fun关联的实体为函数(更确切的说是一个可以作为逻辑函数使用的对象)。
4行与6行相同,11行与13行不同。这是缘于python内部的缓存机制,在为实体开辟内存时进行了优化。
只适用于小整数(至于这个小的定义,已经在python中写死,目前不必深究)。
8行代表用来验证 m为A的一个实体
3. 符号与实体如何关联 __class__, __base__, __bases__
3.1 定义一个符号
定义一个实体同时即为实体声明了一个符号,同时可以增加/删除其它符号对本实体的关联。如:
3.2 实例化一个类
对于实例化,只是在对象a中增加了一个对A的关联符号。所以会出现14-18行的行为结果。
3.2 继承一个类
对于继承,只是在子类B中增加了一个对A的关联符号。所以会出现21-25行,以及12-15行的行为结果。