一、模块
1、定义:模块就是程序。如何python程序都可作为模块导入,供其他程序调用。模块名 = 源码程序文件名。如以下程序就是一个模块
#hello.py
print('hello world!')
2、import导入模块时注意
(1)路径问题。在python解释器中,对模块的搜索路径是特定的,解释器会在固定的几个路径去搜索你要导入的模块,如果导入的是python集成的标准库的模块,正常情况下都能找到。如果是导入自己写的模块,则需要注意解释器的搜索路径问题,有可能解释器找不到这个模块。所以导入前,需要将该模块的路径添加到解释器搜索路径。可执行以下命令添加路径(假设该模块在C:/python目录):
>>import sys
>> sys.path.append('C:/python')
(2)模块的导入操作,只执行一次。如果不是的话,想两个模块内部代码相互导入对方的话,就死循环了。
但是如果一定要重新导入,可用模块importlib中的函数reload,注意一定要将reload的返回结果重新复制给之前已经导入的模块,才能替换旧的模块。如,你修改了某个模块,希望重新导入,可用它:
>>import importlib
>> hello = importlib.reload(hello)
3、模块是用来下定义的
(1)在模块的全局作用域内(非函数体内)定义的类、函数、变量均是该模块的属性,可以通过 · 访问。这种模块化机制有利于代码重用。
(2)在模块中添加测试代码,检查模块功能是否符合预期。测试代码,通常希望模块作为一个程序运行的时候去执行,当被导入另一个程序中时不被执行。 为此,用到变量 __name__
在主程序中,包括解释器交互式命令提示符,__name_ = '__main__'
在模块内,__name__ = 模块名。 hello.__name__ = 'hello'
故,为让测试代码运行合理,将其放入if语句内
if __name__ = '__main__':
testcode()
如此,模块被导入时不会执行testcode,只有被当做程序执行时才会运行testcode
4、让模块可用,即让解释器能找到模块。根据前面介绍,主要有两种方法,一是将模块放在正确位置,即解释器默认的搜索路径。二是,使用模块前,先告诉解释器去哪里找。
5、包(package)。即多个模块放到一个目录下,包本身也是一种模块,但是可包含多个模块。模块扩展名是.py,包则是一个目录。注意以下三点
(1)目录必须包含文件 __init__.py。若将包像普通模块导入,则__init_.py的内容就包的内容,通过 package_name.attri_name来访问该文件内定义的属性。
(2)要将模块放入包内,只要将模块文件放进包目录即可。另,可在包内嵌套其他包。假设有一个名为drawing的包,要往其中加入shaps和colors模块,则最终会有以下目录结构:
~/python/ PYTHONPATH中的目录
~/python/drawing/ 包目录(即包drawing)
~/python/drawing/__init__.py 包代码,即模块drawing。如果直接import drawing,那么drawing就是一个普通模块,内容 即__init__.py的内容
~/python/drawing/shapes.py 模块shapes
~/python/drawing/colors.py 模块colors
几种用法说明:
import drawing #只导入模块drawing,即只用__inti__.py的内容
import drawing.colors #导入包drawing中的colors模块,必须用全名 drawing.colors使用该模块
from drawing import shapes #导入包中的shapes模块,可以直接用简化名shapes来使用该模块
二、探索模块:知道模块内有哪些属性、模块干嘛用的、如何找到模块源码。。。
1、模块包含什么
(1)dir()函数,列出对象的所有属性。作用在模块上,列出模块内所有函数、类、变量等。用法 dir(module_name),注意要先导入才能查到哦。
dir(module_name)出来的结果,有些是以下划线开头的,根据约定它们不是给外部使用的,因此可以用进行过滤:
>>[n for n in dir(module_name) if not n.startswith('_')]
(2)变量__all__:定义模块的公有接口,告诉解释器,当导入模块的所有名称时有哪些接口是可用的。
__all__里存放这一个列表,里面有模块的一些接口。当导入模块所有名称时:
from module_name import *
则导入的只是__all__内的东西,并不是dir(module_name)输出的全局名称。在import *方式导入时起到了过滤作用。
如果没有设置__all__,则以import * 方式导入时,会导入所有不以下划线开头的全局名称。
(3)使用help()函数。可以查询某个模块,或者某个模块内的函数的信息。
(4)模块文档。 module_name.__doc__,并不是所有模块都包含模块文档,可能没有__doc__特性
(5)源码。module_name.__file__,有些源码未必看得懂,可能是解释器的组成部分(如模块sys就是解释器相关模块),也可能是C语言写的。