Python--模块与包
2018-11-29 09:47:00来源:博客园 阅读 ()
模块
1、什么是模块?
一个模块就是一个Python文件,文件名就是模块名字加上.py后缀。因此模块名称也必须符合变量名的命名规范。
1 使用python编写的代码(.py文件)
2 已被编译为共享库或DLL的C或C++扩展
3 包好一组模块的包
4 使用C编写并链接到python解释器的内置模块
2、为什么要使用模块?
如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。
随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用,
3、如何使用模块?
- 方式一:import
- 方式二:from ... import ...
import
首先,自定义一个模块my_module.py,文件名my_module.py,模块名my_module
name = "我是自定义模块的内容..." def func(): print("my_module: ", name) print("模块中打印的内容...")
在import一个模块的过程中,发生了哪些事情?
# 用import导入my_module模块 import my_module >>> 模块中打印的内容... # 怎么回事,竟然执行了my_module模块中的print语句 import my_module import my_module import my_module import my_module import my_module >>> 模块中打印的内容... # 只打印一次
从上面的结果可以看出,import一个模块的时候相当于执行了这个模块,而且一个模块是不会重复被导入的,只会导入一次(python解释器第一次就把模块名加载到内存中,之后的import都只是在对应的内存空间中寻找。)成功导入一个模块后,被导入模块与文本之间的命名空间的问题,就成为接下来要搞清楚的概念了。
被导入模块与本文件之间命名空间的关系?
假设当前文件也有一个变量为: name = 'local file', 也有一个同名的func方法。
# 本地文件 name = "local file" def func(): print(name) # 本地文件有跟被导入模块同名的变量和函数,究竟用到的是哪个呢? import my_module print(my_module.name) # 根据结果可以看出,引用的是模块里面的name my_module.func() # 执行的是模块里面的func()函数 >>> 模块中打印的内容... 我是自定义模块的内容... my_module: 我是自定义模块的内容... print(name) # 使用的是本地的name变量 func() # 使用的是本地的func函数 >>> local file local file
在import模块的时候发生了下面的几步:
1、先寻找模块
2、如果找到了,就在内存中开辟一块空间,从上至下执行这个模块
3、把这个模块中用到的对象都收录到新开辟的内存空间中
4、给这个内存空间创建一个变量指向这个空间,用来引用其内容。
总之,模块与文件之间的内存空间始终是隔离的
给导入的模块取别名,用as关键字
如果导入的模块名太长不好记,那么可以通过“import 模块名 as 别名”的方式给模块名取一个别名,但此时原来的模块就不再生效了(相当于创建了新的变量名指向模块内存空间,断掉原模块名的引用)。
# 给my_module模块取别名 import my_module as sm print(sm.name) >>> 我是自定义模块的内容... print(my_module.name) # 取了别名后,原来的模块名就不生效了 >>> NameError: name 'my_module' is not defined
给模块去别名,还可以使代码更加灵活,减少冗余,常用在根据用户输入的不同,调用不同的模块。
# 按照先前的做法,写一个函数,根据用户传入的序列化模块,使用对应的方法 def dump(method): if method == 'json': import json with open('dump.txt', 'wb') as f: json.dump('xxx', f) elif method == 'pickle': import pickle with open('dump.txt', 'wb') as f: pickle.dump('xxx', f) # 上面的代码冗余度很高,如果简化代码?通过模块取别名的方式,可以减少冗余 def dump(method): if method == 'json': import json as m elif method == 'pickle': import pickle as m with open('dump.txt', 'wb') as f: m.dump('dump.txt', f)
如何同时导入多个模块?
方式一:每行导入一个模块
import os import sys import time
方式二:一行导入多个模块,模块之间通过逗号“,”来分隔
import os, sys, my_module
但是,根据PEP8规范规定使用第一种方式,并且三种模块有先后顺序(内置>第三方>自定义)
# 根据PEP8规范 import os import django import my_module
模块搜索路径
通过sys内置模块,我们知道sys.path存储了所有模块的路径,但是正常的sys.path的路径中除了内置模块,第三方模块所在的路径之外,只有一个路径是永远正确的,就是当前执行的文件所在目录。一个模块是否能够被导入,就取决于这个模块所在的目录是否在sys.path中。
python解释器在启动时会自动加载一些模块,可以使用sys.modules查看
在第一次导入某个模块时(比如my_module),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用
如果没有,解释器则会查找同名的内建模块,如果还没有找到就从sys.path给出的目录列表中依次寻找my_module.py文件。
所以总结模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块
需要特别注意的是:我们自定义的模块名不应该与系统内置模块重名。
模块和脚本
运行一个py文件有两种方式,但是这两种执行方式之间有一个明显的差别,就是__name__。
1、已脚本的方式执行:cmd中“python xxx.py” 或者pycharm等IDE中执行
__name__ = '__main__'
2、导入模块时执行:import模块,会执行该模块。
__name__ = 模块名
然而,当你有一个py文件既可以作为脚本执行,又可以作为模块提供给其他模块引用时,这时作为模块需要导入时而不显示多余的打印逻辑/函数调用,所以这些逻辑可以放在“if __name__ = '__main__': xxx” 代码块中。
这样py文件作为脚本执行的时候就能够打印出来,以模块被导入时,便不会打印出来。
from ... import ...
from...import是另一种导入模块的形式,如果你不想每次调用模块的对象都加上模块名,就可以使用这种方式。
在from ... import ... 的过程中发生了什么事儿?
from my_module import name, func print(name) # 此时引用模块中的对象时,就不要再加上模块名了。 func()
1、寻找模块
2、如果找到模块,在内存中开辟一块内存空间,从上至下执行模块
3、把模块中的对应关系全部都保存到新开辟的内存空间中
4、建立一个变量xxx引用改模块空间中对应的xxx, 如果没有import进来的时候,就使用不了。
from ... import ... 方式取别名
与import方式如出一辙,通过"from 模块名 import 对象名 as 别名"。
from my_module import name as n, func as f
from ... import *
import * 相当于把这个模块中的所有名字都引入到当前文件中,但是如果你自己的py文件如果有重名的变量,那么就会产生不好的影响,因此使用from...import *时需要谨慎,不建议使用。
* 与 __all__
__all__是与*配合使用的,在被导入模块中增加一行__all__=['xxx','yyy'],就规定了使用import *是只能导入在__all__中规定的属性。
# 在my_module模块中定义__all__ __all__ = ['name'] name = 'My module...' def func(): print("my_module: ", name) # 在其他文件中通过import *导入所有属性 from my_module import * print(name) >>> My module... func() >>> NameError: name 'func' is not defined
拓展知识点:
(1)pyc文件与pyi文件 *
pyi文件:跟.py一样,仅仅作为一个python文件的后缀名。
pyc文件: python解释器为了提高加载模块的速度,会在__pycache__目录中生成模块编译好的字节码文件,并且对比修改时间,只有模块改变了,才会再次编译。pyc文件仅仅用于节省了启动时间,但是并不能提高程序的执行效率。
(2)模块的导入和修改 *
1.导入模块后,模块就已经被加载到内存中,此后计算对模块进行改动,读取的内容还是内存中原来的结果。
2.如果想让改动生效,可以通过“from importlib import reload”, 需要'reload 模块名'重新加载模块,改动才生效。
(3)模块的循环使用 ****
谨记模块的导入必须是单链的,不能有循环引用,如果存在循环,那么就是程序设计存在问题。
(4)dir(模块名) ***
可以获得该模块中所有的名字,而且是字符串类型的,就可以通过反射去执行它。
包
包是一种通过‘.模块名’来组织python模块名称空间的方式。
(1)无论是import形式还是from ... import 形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
(2)包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
(3)import导入文件时,产生名称空间中的名字来源与文件,import包,产生的名称空间的名字同样来源与文件,即包下的__init__.py,导入包本质就是在导入文件
注意:
1、在python3中,即使包下没有__init__.py文件,import包仍然不会报错,而在python2中,包下一定要有该文件,否则import包会报错
2、创建包的目的不是为了运行,而是被导入使用,记住,包只有模块的一种形式而已,包即模块
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- python3 enum模块的应用 2019-08-13
- 利用python自动生成verilog模块例化模板 2019-08-13
- Python random模块(以后用到一个再更新一个) 2019-07-24
- xadmin进行全局配置(修改模块名为中文以及其他自定义的操作 2019-07-24
- concurrent.futures模块简单介绍(线程池,进程池) 2019-07-24
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash