2019/12/03 04-包
模块名全小写,加下划线即可,模块名就是文件名,文件名尽量不冲突,这个文件名有搜索顺序,搜索顺序和模块的加载和缓存是有顺序的
模块的运行需要解释器,解释器工作过程中需要初始化字典sys.modules,然后把内建的builtin加载起来,然后加载main模块。
最后要搜索一个模块要使用,sys.path工具,使用sys.path前提是sys。modules没找到,也就是模块根本没加载过才需要去sys.path里去找
这个用途很简单,要么当主模块用,如果当其它模块用,这段代码就不用执行 了
模块的源文件在哪里
模块编译后的规格
如果模块是包,会有__package__这个属性
创建一个普通目录m
可以导入
m本身是包含,package,path,spec,说明是可以当模块对象来看的,python中把这个目录只要你放在运行环境中,是可以当作模块来看的,目录也是个特殊文件
在m目录下建立一个m1.py
m.m1说明跑到m1.py里 了
定义一个特殊文件__init__
对于一个目录来讲,想要当做模块看,想在这个模块上,有代码,代码肯定不写在目录上,借助一个特殊文件__init__,这是用来初始化特殊模块的,初始化目录的,这个目录是一个特殊的模块,这个模块需要写代码就是这样的文件
如果目录含有__init__特殊文件,叫做包package
访问m1,就必须写m.m1跟os.path一个道理
这个包借助init特殊文件来写代码
类型,这个init文件是代表包自身,为包写一些代码就可以在这里处理
包里的模块称为子模块
运行m1.py改成这样
运行,获取的是m的信息
在t运行会有m信息
dir的作用是,()是收集当前作用环境里,顶级写的,toplevel,这东西最大收集范围就是所在的模块,模块就是边界,
dir是超不出自己所在模块的,模块是非常强的边界,模块类似国界与国界,定义的所有类,所有东西,都被模块所管理
这只是把类对象,加个名字来引用,还是归os的,python中模块是非常强的边界,dir出不了模块,
globals是个字典
现在取到key了
排个序,dir默认就是排序的
观察如下
把干扰项去掉,再执行
global全局,上面的global执行的时候还没有x
挪一下位置
局部变量,global是不关心的,显示模块顶层代码的所有标识符
这里的local就受局部作用域的影响了,现在只能看到x函数内部的东西
dir上面都不写其实就是locals
现在代码搬到t2中
写在外面就一样了,下面三行
所以都能访问t2.x,模块是一个非常强的边界,就算你有全局变量,也一样跨越不了模块边界,模块是最强的边界 了
全局作用域以模块为边界,局部作用域的时候locals肯定受影响,全局是模块中大家都共用的东西,模块有多大,它的范围就有多大(这就是为什么当初闭包打印global还能看见里面)
用getattr方式也可以访问
开始创建目录
现在有这样一个目录
加一段代码
m包和t.模块在一起
import m 发现sys.modules里没有加载,现在sys.path找当前运行环境里有没有m的包,所以m就加载起来了
可以这么使用
m1.py里修改
m.m1这么写是可以的
不会把m1加进来
m22模块也写一下
这样访问是没有问题的
换一种方式写
sys其实写不写都已经导入了
m被加载到sys.modules里了
前面加m包名,否则前面m1有可能跟其他模块名冲突
试试m2.m21
模块加载的本质是,把模块代码从磁盘读取出来,从上往下解释执行一遍,加载完之后,解释器执行完,生成一个模块对象,这个模块对象就跟导入的名词建立关系
这样访问不行,但是m.下面确实有m.m1,现在m属性字典里没有叫m1的所以报错
需要用就导入一下,先看这个对象有没有这个属性,没有属性查看这里面有没有模块,
这其实会藏在m对象的字典上,所以下次访问m.m1就没有问题了
把import m.m1去掉,就没有m1,这就是为什么不行
python2最好不要这么做,删除之后就报错,就不是包了
包能够更好的组织模块,尤其是大的模块,其代码行数很多,可以把它拆分成很多子模块,便于使用某些功能就加载相应的子模块
包目录中init_ py 是在包第 一次导入的时候就会执行 ,内容可以为空 ,也可以是 用于该包初始化工作的代码 ,
有sys.modules保证,包只会加载一次,sys.modules其实就是模块加载的缓存
模块也是封装,如同类、函数,不过它能够封装变量、类函数。模块可以封装类,任意的对象
模块就是命名空间,其内部的顶层标识符,都是它的属性,可以通过dict_ 或dir(module)查看。
包也是模块,但模块不一定是包,包是特殊的模块,是一一种组织方式,它包含_path_ 属性
是对后面写的对象是尽量去收集属性的】
,它包含_path_ 属性
借助init文件写代码
告诉你没有path,有file
t变成主模块,拿到当前主模块所在运行环境的目录
主模块文件拿到,就可以拿到主模块运行目录,就可以知道当前路径在哪里
这个json是不会加入当前名词空间中,encoder是加载 ,所以json.dump是加载不进去的
sys.modules只放模块或者包,不放函数
可以,还是要看dir到底放什么,如果encoder是一个函数是不允许的,但是这个地方是一个模块,就是可以的