模块和包

1.什么是模块

  一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀

  其实import加载的模块分别为死歌通用类别:

    1.使用pytho编写的代码(.py文件)

    2.已被编译为共享库或DLL的C或C++扩展

    3.包好一组模块的包

    4.使用C编写并链接到python解释器的内置模块

2.如何自己写一个模块

    创建一个py文件,给它起一个符合变量命名规则的名字,这个名字就是模块名

3.模块的导入

  导入一个模块就是执行一个模块

  模块导入的过程中发生了什么:

    1.找到这个模块

    2.判断这个模块是否被导入过了

    3.如果没有被导入过:

      创建一个属于这个模块的命名空间

      让模块的名字指向这个空间

      执行这个模块中的代码

  给模块起别名:起了别名之后,就只能使用这个模块的别名引用变量了

  导入多个模块:

    import os,time

  规范建议:

    模块应该一个一个的导入:

      内置模块

      扩展(第三方)模块

      自定义模块

  from  import  

    模块导入的过程中发生了什么:

      1.找到要被导入的模块

      2.判断这个模块是否被导入过

      3.如果这个模块没被导入过

        创建一个属于这个模块的命名空间

        执行这个文件

        找到要导入的变量

        给导入的变量创建一个引用,指向要导入的变量

 1 #测试一:导入的函数read1,执行时仍然回到my_module.py中寻找全局变量money
 2 #demo.py
 3 from my_module import read1
 4 money = 1000
 5 read1()
 6 
 7 #测试二:导入的函数read2,执行时需要调用read1(),仍然回到my_module.py中找read1()
 8 #demp.py
 9 from my_module import read2()
10 def read1():
11     print("1")
12 read2()

如果当前有重名read1或者read2,那么会有覆盖效果

1 #测试三:导入的函数read1,被当前位置定义的read1覆盖掉了
2 #demo.py
3 from my_module import read1
4 def read1():
5     print("1")
6 read1()
7 执行结果:
8 from the my_module.py
9 1

from my_module import *把my_module中所有的不是以下划线(_)开头的名字都导入到当前位置

from my_module import *
print(money)
print(read1)
print(read2)

执行结果:
from the my_module.py
1000

如果my_module.py中的名字前加_,即_money,则frommy_module import *,_money不能被导入

模块引用中的情况:模块之间不允许循环引用

4.模块的加载与修改

  每个模块只被导入一次,放入到sys.modules中,如果改变了模块中的内容,必须重启程序

5.把模块当成脚本来使用

  可以通过模块的全局变量__name__来查看模块名:

    当做脚本运行:

      __name__等于'__main__'

    当做模块导入:

      __name = 模块名

  作用:用来控制.py文件在不同的应用场景下执行不同的逻辑

  if __name__ == '__main__':

 1 def fib(n):
 2     a,b = 0,1
 3     while b<n:
 4         print(b,end = '')
 5         a, b = b, a+b
 6     print()
 7 
 8 if __name__ == "__main__":
 9     print(__name__)
10     num = input("num:")
11     fib(int(num))

py文件:直接运行这个文件,这个文件就是一个脚本

    导入这个文件,这个文件就是一个模块

当一个py文件:

  当做一个脚本的时候:能够独立的提供一个功能,能自主完成交互

  当成一个模块的时候,能够被导入这调用这个功能,不能自主交互

一个文件中的__name__变量:

  当这个文件被当做脚本执行的时候:__name__ == '__main__'

  当这个文件被当做模块导入的时候:__name__ == '模块的名字'

6.模块搜索路径

  在第一次导入某个模块时,会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用,如果没有,解释器则会查找同名的内建模块,如果还没有找到就从sys.path给出的目录列表中依次寻找这个模块

所以模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块

7.包

  1.文件夹中有一个__init__.py文件

  2.是几个模块的集合

  3.无论是import形式还是from..import形式,凡是在导入语句中(而不是在使用时)遇到带点的,这是关于包才有的导入语法

  4.包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)

  5.import导入文件时,产生名称空间中的名字来源于文件,import包产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件

  6.导入一个包相当于执行了这个包下面的__init__.py文件

关于包相关的导入语句也分为import和from..import..两种,但无论是哪种,在什么位置,都遵循一个原则:

      凡是在导入时带点的,点的左边都必须是一个包

对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(他们都可以用点的方式调用自己的属性)

绝对导入:

  在执行一个py脚本的时候,这个脚本以及这个脚本同级的模块中只能用绝对导入

  缺点:

    所有的导入都要从一个根目录下往后解释文件夹之间的关系

    如果当前导入包的文件和被导入的包的位置关系发生了变化,那么所有的init文件都要做相应的调整

1 import glance
2 glance.__init__.py
3 import api
4 sys.path = [path]
5 glance.api.policy.get()

相对导入:

  不需要去反复的修改路径

  只要一个包中的所有文件夹和文件的相对位置不发生改变,init文件就不需要调整

  不需要去关心当前这个包和被执行的文件之间的层级关系

  缺点:

    含有相对导入的py文件不能被直接执行

    必须放在包中被导入的调用才能正常的使用

如果只是从包中导入模块的话,就不需要做任何多余的操作

如果希望导入包的时候,能够顺便的把模块也导入进来,需要设计init文件夹

原文地址:https://www.cnblogs.com/s593941/p/9525704.html