2019/12/03 04-包

2019/12/03 04-包
模块名全小写,加下划线即可,模块名就是文件名,文件名尽量不冲突,这个文件名有搜索顺序,搜索顺序和模块的加载和缓存是有顺序的
模块的运行需要解释器,解释器工作过程中需要初始化字典sys.modules,然后把内建的builtin加载起来,然后加载main模块。
最后要搜索一个模块要使用,sys.path工具,使用sys.path前提是sys。modules没找到,也就是模块根本没加载过才需要去sys.path里去找

2019/12/03 04-包
2019/12/03 04-包
这个用途很简单,要么当主模块用,如果当其它模块用,这段代码就不用执行 了2019/12/03 04-包2019/12/03 04-包
模块的源文件在哪里
2019/12/03 04-包2019/12/03 04-包
模块编译后的规格
2019/12/03 04-包2019/12/03 04-包
如果模块是包,会有__package__这个属性
2019/12/03 04-包2019/12/03 04-包2019/12/03 04-包2019/12/03 04-包
创建一个普通目录m
2019/12/03 04-包
可以导入
2019/12/03 04-包
m本身是包含,package,path,spec,说明是可以当模块对象来看的,python中把这个目录只要你放在运行环境中,是可以当作模块来看的,目录也是个特殊文件2019/12/03 04-包
在m目录下建立一个m1.py
2019/12/03 04-包
m.m1说明跑到m1.py里 了
2019/12/03 04-包
定义一个特殊文件__init__2019/12/03 04-包
对于一个目录来讲,想要当做模块看,想在这个模块上,有代码,代码肯定不写在目录上,借助一个特殊文件__init__,这是用来初始化特殊模块的,初始化目录的,这个目录是一个特殊的模块,这个模块需要写代码就是这样的文件
如果目录含有__init__特殊文件,叫做包package
2019/12/03 04-包2019/12/03 04-包
访问m1,就必须写m.m1跟os.path一个道理
2019/12/03 04-包
这个包借助init特殊文件来写代码2019/12/03 04-包
类型,这个init文件是代表包自身,为包写一些代码就可以在这里处理2019/12/03 04-包
包里的模块称为子模块
2019/12/03 04-包
运行m1.py2019/12/03 04-包2019/12/03 04-包改成这样
2019/12/03 04-包2019/12/03 04-包
运行,获取的是m的信息
2019/12/03 04-包
在t运行会有m信息2019/12/03 04-包
dir的作用是,()是收集当前作用环境里,顶级写的,toplevel,这东西最大收集范围就是所在的模块,模块就是边界,
dir是超不出自己所在模块的,模块是非常强的边界,模块类似国界与国界,定义的所有类,所有东西,都被模块所管理
2019/12/03 04-包
这只是把类对象,加个名字来引用,还是归os的,python中模块是非常强的边界,dir出不了模块,
2019/12/03 04-包
globals是个字典2019/12/03 04-包
现在取到key了2019/12/03 04-包
排个序,dir默认就是排序的
2019/12/03 04-包
观察如下2019/12/03 04-包
把干扰项去掉,再执行
2019/12/03 04-包
global全局,上面的global执行的时候还没有x
2019/12/03 04-包
挪一下位置
2019/12/03 04-包
局部变量,global是不关心的,显示模块顶层代码的所有标识符2019/12/03 04-包
这里的local就受局部作用域的影响了,现在只能看到x函数内部的东西
2019/12/03 04-包
dir上面都不写其实就是locals2019/12/03 04-包
现在代码搬到t2中2019/12/03 04-包2019/12/03 04-包
写在外面就一样了,下面三行
2019/12/03 04-包
所以都能访问t2.x,模块是一个非常强的边界,就算你有全局变量,也一样跨越不了模块边界,模块是最强的边界 了
2019/12/03 04-包
全局作用域以模块为边界,局部作用域的时候locals肯定受影响,全局是模块中大家都共用的东西,模块有多大,它的范围就有多大(这就是为什么当初闭包打印global还能看见里面)
用getattr方式也可以访问2019/12/03 04-包2019/12/03 04-包2019/12/03 04-包2019/12/03 04-包2019/12/03 04-包
开始创建目录
2019/12/03 04-包2019/12/03 04-包2019/12/03 04-包2019/12/03 04-包
现在有这样一个目录2019/12/03 04-包
加一段代码2019/12/03 04-包2019/12/03 04-包
m包和t.模块在一起2019/12/03 04-包
import m 发现sys.modules里没有加载,现在sys.path找当前运行环境里有没有m的包,所以m就加载起来了2019/12/03 04-包
可以这么使用
2019/12/03 04-包2019/12/03 04-包
m1.py里修改
2019/12/03 04-包
m.m1这么写是可以的2019/12/03 04-包
不会把m1加进来2019/12/03 04-包
m22模块也写一下
2019/12/03 04-包
这样访问是没有问题的
2019/12/03 04-包
换一种方式写
2019/12/03 04-包2019/12/03 04-包2019/12/03 04-包
sys其实写不写都已经导入了
m被加载到sys.modules里了

2019/12/03 04-包
前面加m包名,否则前面m1有可能跟其他模块名冲突2019/12/03 04-包
试试m2.m212019/12/03 04-包
模块加载的本质是,把模块代码从磁盘读取出来,从上往下解释执行一遍,加载完之后,解释器执行完,生成一个模块对象,这个模块对象就跟导入的名词建立关系

这样访问不行,但是m.下面确实有m.m1,现在m属性字典里没有叫m1的所以报错
2019/12/03 04-包
需要用就导入一下,先看这个对象有没有这个属性,没有属性查看这里面有没有模块,2019/12/03 04-包
这其实会藏在m对象的字典上,所以下次访问m.m1就没有问题了
2019/12/03 04-包
把import m.m1去掉,就没有m1,这就是为什么不行
2019/12/03 04-包
python2最好不要这么做,删除之后就报错,就不是包了
2019/12/03 04-包2019/12/03 04-包
包能够更好的组织模块,尤其是大的模块,其代码行数很多,可以把它拆分成很多子模块,便于使用某些功能就加载相应的子模块
包目录中init_ py 是在包第 一次导入的时候就会执行 ,内容可以为空 ,也可以是 用于该包初始化工作的代码 ,
有sys.modules保证,包只会加载一次,sys.modules其实就是模块加载的缓存

2019/12/03 04-包
模块也是封装,如同类、函数,不过它能够封装变量、类函数。模块可以封装类,任意的对象

模块就是命名空间,其内部的顶层标识符,都是它的属性,可以通过dict_ 或dir(module)查看。

包也是模块,但模块不一定是包,包是特殊的模块,是一一种组织方式,它包含_path_ 属性

是对后面写的对象是尽量去收集属性的
2019/12/03 04-包
,它包含_path_ 属性2019/12/03 04-包
借助init文件写代码2019/12/03 04-包
告诉你没有path,有file2019/12/03 04-包
t变成主模块,拿到当前主模块所在运行环境的目录
主模块文件拿到,就可以拿到主模块运行目录,就可以知道当前路径在哪里
2019/12/03 04-包2019/12/03 04-包2019/12/03 04-包
这个json是不会加入当前名词空间中,encoder是加载 ,所以json.dump是加载不进去的
sys.modules只放模块或者包,不放函数

2019/12/03 04-包
可以,还是要看dir到底放什么,如果encoder是一个函数是不允许的,但是这个地方是一个模块,就是可以的2019/12/03 04-包2019/12/03 04-包2019/12/03 04-包