*1 什么是模块* 模块就是一系列功能的集合体 模块有三种来源 1. 内置的模块 2. 第三方的模块 3. 自定义模块 模块的格式: 1 使用python编写的.py文件(常用) 2 已被编译为共享库或DLL的C或C++扩展 3 把一系列模块组织到一起的文件夹(注:每一个包目录下面都会有一个*init*.py 的文件,这个文件是必须存在的,否则,Python 就把这个目录当成普通目录,而不是一个包。*init*.py 可以是空文件,也可以有 Python 代码,因为*init*.py 本身就是一个模块,而它的模块名就是 mycompany) 4 使用C编写并链接到python解释器的内置模块 *2 为何要用模块* 1. 使用内置的或者第三方模块的好处是: 拿来主义,可以极大提升开发效率 2. 使用自定义模块的好处是: 可以减少代码冗余(抽取我们自己程序中要公用的一些功能定义成模块,然后程序的各部分组件都去模块中调用共享的功能) *3 如何用模块* 大前提: 一定要区分开谁是执行文件,谁是被导入模块 _*import*_ 例: #spam.py money=1000 def read1(): print('spam模块:',money) def read2(): print('spam模块') read1() def change(): global money money=0 文件名是spam.py,模块名则是spam *首次导入模块发生3件事* 1. _会产生一个模块的名称空间_ 2. _执行文件spam.py,将执行过程中产生的名字都放到模块的名称空间中_ 3. _在当前执行文件的名称空间中拿到一个模块名,该名字指向模块的名称空间_ _之后的导入,都是直接引用第一次导入的成果,不会重新执行文件_ import spam # 之后引用的同名模块不会再重复执行 import spam import spam import spam *在执行文件中访问模块名称空间中名字的语法:模块名.名字* import spam print(spam.x) # 指名道姓地跟spam要名字x,肯定不会与当前执行文件中的名字冲突 *总结* import导入模块:在使用时必须加上前缀:模块名. 优点: _指名道姓地向某一个名称空间要名字,肯定不会与当前名称空间中的名字冲突_ 缺点: _但凡应用模块中的名字都需要加前缀,不够简洁_ * 一行导入多个模块(不推荐) import spam, os, time * 可以为模块起别名(注意:模块名应该全为小写) import spam as sm _form .. import .._ 例: #spam.py __all__ = ['money','read1'] #from spam import * money=1000 def read1(): print('spam模块:',money) def read2(): print('spam模块') read1() def change(): global money money=0 money=200 *首次导入模块发生3件事* 1. _创建一个模块的名称空间_ 2. _执行文件spam.py,将执行过程中产生的名字都放到模块的名称空间中_ 3. _在当前执行文件中直接拿到一个名字,该名字就是执行模块中相对应的名字的_ from spam import money,read1,read2,change money=200 print(money) read1=123 read1() read2() change() print(money) *总结* from...import... 优点: _使用时,无需再加前缀,更简洁_ 缺点: _容易与当前名称空间中的名字冲突_ from spam import * 代表从被导入模块中拿到所有名字(不推荐使用) # from spam import money,read1,read2,change # from spam import # *all* = ['money','read1'] print(money) print(read1) print(read2) print(change) 起别名 from spam import read1 as r1 r1()
内容: 1. 模块的循环导入 2. 区分python文件的两种用途 3. 模块的搜索路径 4. 模块的绝对导入 5. 模块的相对导入 6. 软件开发的目录规范 ''' 首次导入模块发生的三件事 1. 产生一个模块的名称空间 2. 执行被导入模块的代码,将产生的名字全都放在模块的名称空间里 3. 当执行文件时,拿到一个被导入模块的名字,这个名字就指向被导入模块的名称空间的那个名字 ''' *第二次再导入相同模块时,就直接引用第一次导入模块时的那个名称空间。* *模块的循环导入* m1.py #m1 print("from m1") from m2 import y x = "m1" m2.py #m2 print("from m2") from m1 import x y = "m2" run.py import m1 *执行run程序 导入m1,执行到 from m2 import y 会去导入 m2 并且寻找y的内存地址,但是导入m2之后,* *又执行了from m1 import x,这时候又会去回到m1中找x的内存地址,但是x这时候还没有被放入内存中,就会发生锁一样的东西,* *程序就会报错。* 如何来解决循环导入,并解决第1题中的循环导入问题 方法一: 把x="m1"放到 from m2 import y 上面,就等于先把x放入到内存里,这时候继续往下执行,执行到m2中的from m1 import x的时候, 程序就找到x的内存地址。锁就自然就开了。 方法二: 将from m2 import y定义在函数里面,先放到内存中,这时候就会自然向下执行x="m1",将from m1 import x也定义为函数, 将函数的内存地址也给导入到m1中,也就是from m2 import y,f2 并且执行f2() 在主程序run里面调用m1中的函数f1,这时候就不会发生锁了 区分python文件的两种用途 *#当文件被执行时__name__=='__main__' (执行文件)* *#当文件被导入时__name__=='模块名' (被导入的模块)* *当加入 if __name__=='__main__':的时候* *在这条语句下面的方法调用,只会在执行此文件时才会被调用,在其他文件里是运行不了的。* 要分清大前提:什么是执行文件,什么是被导入文件 模块的搜索路径 模块搜索路径的优先级: *1. 内存中已经加载过的* *2. 内置模块* *3. Sys.path(环境变量)中的 第一个值是当前执行文件所在的文件夹* (pychram会添加一条当前目录的父目录,放在第二个位置,帮助我们识别一些其他的路径,可以让我们写程序的时候,可以用TAB键补齐语法) # 环境变量是以当前执行文件为准的 # 强调:所有被导入的模块参照环境变量sys.path都是以执行文件为准的 *注:命名模块时,不可与内置模块的名字冲突*(模块搜索路径,内置的优先级比sys.path的高) *模块的绝对导入:以sys.path为基准寻找模块的方式* * 优点:执行文件与被导入的模块都可以使用* * 缺点:所有的被导入的模块,都是参照执行文件的sys.path,导入麻烦 * *模块的相对导入:参照当前文件的文件夹为起始位置开始查找,称之为相对导入。* *优点:导入更加简单* * 缺点:只能在被导入的模块中使用,不能再执行文件中使用。(执行文件只能用绝对导入)* * 符号:. 表示当前文件所在文件的文件夹。. . 表示前文件所在文件的文件夹的上一级。. . .表示上一级的上一级文件夹* 比如有A,B,C三个文件 在A中导入B,如果想在B中导入C,模块的搜索路径是以A为准的。A是执行文件,B,C是模块 环境变量是以当前执行文件为准的,所有的被导入的模块,参照的sys.path都是执行文件的。(sys.path是个列表,里面有多个值) Import sys. Sys.path.append(r”路径”)可添加sys.path。 *软件开发的目录规范* *bin:放程序入口* *conf:放配置文件* *core:放业务逻辑的文件* *db:放关于业务数据的文件* *lib:放需要公共使用的包或模块* *log:放日志文件* *Readme:写关于软件的使用手册或一些介绍* 包的使用 1、在导入时带点的,点的左边必须是一个包,这是导入包特有的语法 2、包内,模块直接的导入应该使用from。。。import 。。。 3、from 。。。 import。。。,import后必须是一个明确的名字,没有任何的前缀 例如: from a.b.c.d.f import g.h.x #错误 1、f左边必须都是包 2、import后的名字不能有任何前缀 #模块名约定用全小写 #包内的模块没有右键运行的需求 2、格式化的字符串 print(time.strftime('%Y-%m-%d %H:%M:%S %p'))