1.什么叫python的模块?
一个.py文件就是一个模块(通常用小写字母命令),这个模块可以有class, function, variable等符号组成
2.什么叫package,python的package的形式,__init__的作用?
#目录A下有一个__init__.py文件,A就可以认为是一个package,它通常由模块和子包组成,我在python3.6下做实验发现可以不需要显示创建__init__.py,这是python2和python3的形式区别。
#__init__.py也是一个python模块,通常里面什么也不写。这样我们直接import package时,不能使用任何模块,必须使用import package.module或者from package import module的形式
#前者的使用形式是package.module.variable_symbol,后者的使用形式是module.variable_symbol
#当然也可以在__init__.py定义function,class,这样直接import package时就可以直接使用,但是一般不会这么做。
#__init__.py文件会在第一次导包的过程中执行(一个模块多次导相同的包,这个包的__init__.py只会执行一次),所以它的最大作用是用来导入其他package下的某些模块,这样主导模块就可以直接使用被导包中导入的symbol了
#它的另一个作用是可以结合__all__列表变量用来控制主导模块中使用from package import *模块
3.python模块导入的搜索路径(导包机制)
sys.path 查看搜索路径
4.常见的导包的形式(绝对路径和相对路径)
#所谓的相对路径还是绝对路径都是相对于一个包而言的,从package的顶层开始称为绝对路径,使用. .. ...表示相对路径,包内建议用相对路径,入口模块应该在包之外。
5.全局导入和局部导入
#全部用全局导入即可,用局部导入的情况不多,一般约定在.py文件的最开头全局导入。
6.常见的错误的解决办法
#1.同一包下导入模块
#在自定义的包下,多个模块即使在同一包下也不能直接使用import modulename,因为这种形式是导入python自带的moduel,所以我们必须指明包名,使用带packagename的导入方式,如
#import packagename.moduelname [绝对路径] 或者 from . import moduelname [相对路径], 此时这个backage下的__init__.py moudel也是会被执行的
#包内的模块间应该使用相对路径导入, 一般包类的模块不应该作为入口模块[指执行.py文件],在开发这个包时可能会有一个测试包的.py文件,有人将这个文件放在包内作为入口模块,它的作用仅限于开发期的测试,
#个人还是建议将其放在包外测试比较好
#2.不同包下,A包导入B包下模块
#出现这种情况的一个重要原因是没有理解包的作用,一个包应该是具有完整功能的代码块,理论上不应该再去导入和它同级的包,当然包内的子包是可以互相导入使用的,而且应该使用相对路径导入,
#导入这个包的模块(入口模块,也就是.py文件)应该在这个包之外。 如果入口模块在包之内,一种解决方式是重构代码即在将这几个包设计成另一个包的子包[个人推荐这种方式]
#另一方式使用sys.path增加包的搜索路径[个人强烈不推荐,工程大时,代码会很乱,严重违反包的设计原则]
#入口模块的位置对包间模块导包的影响很大,已导入入口模块的模块路径变成入口模块的位置路径而不是该模块本身的位置路径
#3.循环导入(a模块导入b模块,同时b模块导入a模块)
#出先这种情况一般是因为模块代码设计没有设计好,有些指标不治本办法,个人觉得还是重构代码比较好
TEST1:
在 test 目录下, 结构如下:
A.py文件代码:
a包的 __init__.py 代码如下
samedirpakg.py:文件内容如下
执行samedirpakg.py, 结果如下:
当导入a包三次时,我们可以发现__init__模块只执行了一次。
TEST2:
修改a包的 __init__.py , 内容如下:
AA.py代码如下:
修改 samedirpakg.py 如下 并执行它
结果如下:
我们可以发现当一个模块M在a包的__init__文件导入后,另一个模块直接用import a 就可以使用M模块。
TEST3:
b包中B模块导入a包,并且执行B模块,此时必须使用sys.path.append函数来增加包的搜索路径,B.py的代码如下:
运行结果如下:
结论:__package__打印的值为None,理论上应该为b,可见这种方式严重破坏了包的设计原则。
TEST4:
修改b包中的B模块为:
修改工程目录test下的samedirpakg.py模块如下,并执行它
运行结果为:
结论:工程目录不属于包所以__package__的值为None,综合TEST3和TEST4可以得出,入口模块的位置对包间模块导包的影响很大,已导入入口模块的模块路径变成入口模块的位置路径而不是该模块本身的位置路径,所以B.py中可以直接使用import a这种方式虽然没有破坏包的设计原则,但是代码会很混乱,尽量避免TEST4的情况