Python基础之(模块与包)
一、什么是模块
模块就是一组功能的集合体,我们的程序可以导入模块来复用模块的功能
在python中,模块的使用方式都是一样的,但其实细说的话,模块可以分为四个通用类别:
- 使用python编写的代码(.py文件)
- 已被编译为共享库或DLL的C或C++扩展
- 包好一组模块的包
- 使用C编写并链接到python解释器的内置模块
二、为什么使用模块
2.1、从文件级别组织程序,更方便管理。随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用
2.2、拿来主义,提升开发效率。同样的原理,我们也可以下载别人写好的模块然后导入到自己的项目中使用,这种拿来主义,可以极大地提升我们的开发效率
三、模块使用之import
3.1、使用import导入
模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到导入import语句时才执行
import语句是可以在程序中的任意位置使用的,且针对同一个模块为了防止你重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载到内存中的模块对象增加了一次引用,不会重新执行模块内的语句
import test import test #执行,只是没有显示效果 #执行结果 form the test
3.2、第一次导入模块做的三件事
- 为源文件(test模块)创建新的名称空间
- 在新创建的命名空间中执行模块中包含的所有代码
- 创建名字test来引用该命名空间
3.3、为模块起别名
import test as ts #可以将过长的模块命名改成短的,便于操作 #有利于代码的拓展,优化。
3.5、导入多个模块
import sys,os,json # 可以这样写,但是不推荐 #推荐应该这样: import sys import os import json
3.6、from .... import ....
from test import t1 from test import t1 as t #支持as from test import t1,t2,te #支持导入多个 #与import区别 使用from...import...则是将模块中的名字直接导入到当前的名称空间中,所以在当前名称空间中,直接使用名字就可以了、无需加前缀 #from...import...的方式有好处也有坏处:好处:使用起来方便了,坏处:容易与当前执行文件中的名字冲
from ....import * 把模块中所有的不是以下划线(_)开头的名字都导入到当前位置,大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。当然可以使用__all__来控制*
__all__=['name1','name2'] #这样在另外一个文件中用from name import *就这能导入列表中规定的两个名字
3.7、模块的搜索路径
模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块
(Python解释器只认执行文件的os.path,与同级目录无关)
import os import sys dir=os.path.dirname(os.path.dirname(os.path.abspath(__file__)) #上级目录 sys.path.append(dir) #增加sys.path路径
四、py文件的两种功能
#编写好的一个python文件可以有两种用途: 1、脚本,一个文件就是整个程序,用来被执行 2、模块,文件中存放着一堆功能,用来被导入使用 #python为我们内置了全局变量__name__, 当文件被当做脚本执行时:__name__ 等于'__main__' 当文件被当做模块导入时:__name__等于模块名 #作用:用来控制.py文件在不同的应用场景下执行不同的逻辑 if __name__ == '__main__':
五、包
5.1、包是什么
包是一种通过使用‘.模块名’来组织python模块名称空间的方式
具体的:包就是一个包含有__init__.py文件的文件夹,所以其实我们创建包的目的就是为了用文件夹将文件/模块组织起来
需要强调的是:
- 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
- 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包的本质就是一种模块
5.2、导入使用注意事项
- 关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。但对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
- import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
- 包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间
5.3、绝对导入和相对导入
我们的最顶级包是写给别人用的,然后在包内部也会有彼此之间互相导入的需求,这时候就有绝对导入和相对导入两种方式:
绝对导入:以包作为起始
相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)
# 绝对导入: 以执行文件的sys.path为起始点开始导入,称之为绝对导入 # 优点: 执行文件与被导入的模块中都可以使用 # 缺点: 所有导入都是以sys.path为起始点,导入麻烦 # 相对导入: 参照当前所在文件的文件夹为起始开始查找,称之为相对导入 # 符号: .代表当前所在文件的文件夹,..代表上一级文件夹,...代表上一级的上一级文件夹 # 优点: 导入更加简单 # 缺点: 只能在导入包中的模块时才能使用 #注意: #相对导入只能用于包内部模块之间的相互导入,导入者与被导入者都必须存在于一个包内 #试图在顶级包之外使用相对导入是错误的,言外之意,必须在顶级包内使用相对导入,每增加一个.代表跳到上一级文件夹,而上一级不应该超出顶级包