Python学习笔记(七)之Python模块
1. 初始模块
1.1 模块导读
- 首先我们来看一下模块是什么,前面呢我们在一个Python文件中写了一些函数,这些函数写完后我们只能在自己的Python文件中使用,当我们想要让自己编写的函数能够跨文件使用,Python就提供了一种方法,这就是模块了。
1.2 模块定义
- 把一些定义存放在文件中,为一些脚本或者交互式的编译器实例使用,这个文件就被称为
模块
。所以说上面我们写的一些包含函数的Python文件实际上就是一个个模块了。 - 模块是一个包含所有你定义的函数和变量的文件,其后缀名是
.py
。模块可以被别的模块引用和使用,实现在不同的Python文件中使用你编写的函数的功能。而我们平常用的Python标准库,其实就是模块的调用。
1.3 模块实例
-
例1.3.1:
# !/user/bin/python # coding=utf-8 import math __author__ = "zjw" def helloModule(): print "Hello Module!" if __name__ == '__main__': print math.pi helloModule()
-
输出:
3.14159265359 Hello Module!
-
分析:
- 前两行的两个注释是标准注释,第一行的注释可以让文件直接在Unix/Linux/Mac上运行,只对这三个操作系统有效(参考:Python程序 #!/usr/bin/python 的解释),第二行则是表示.py文件本身使用标准UTF-8编码。
- 下面的
import
语句就是导入模块。这里导入了math的模块,我们就有了变量math
指向该模块,利用math
这个变量,我们就可以访问模块中的所有功能了。 - 在下面的
__author__
关键字用来表明作者,在这里我们可以进行署名,标注上自己的笔名。 - 在下面我们定义了一个
helloModule()
函数,紧接着是一个main
函数,分别调用了math
模块中的pi的值,和自己写的函数helloModule()
。
2. 模块导入
2.1 实例分析(关键部分,重点看)
-
直接来看一个例子:
-
这是我建的一个工程和包含的一些Python包和Python文件。注:这里每一module模块中都有一个hello函数,hello函数只有一句输出函数。
-
这里给出了五种不同的调用
test01
包中的module
的方法,都是在main.py
模块中实现的,模块的代码如下:# !user/bin/env python # coding=utf-8 import test01.module01 # 方法1 from test01 import module02 # 方法2 from test01.module03 import hello03 # 方法3 import test01.module04 as m4 # 方法4 from test01.module05 import hello05 as m5 # 方法5 __author__ = "zjw" if __name__ == '__main__': print "Hello world!" test01.module01.hello01() # 方法1 module02.hello02() # 方法2 hello03() # 方法3 m4.hello04() # 方法4 m5() # 方法5
-
输出:
Hello world!
Hello module01!
Hello module02!
Hello module03!
Hello module04!
Hello module05! -
注:这里我们惨遭上面的工程项目的包和模块的相关图,理解代码。
- 根据我的摸索,发现了一个问题,就是Python中的模块的路径都是从项目的根目录开始寻找相应的模块的。所以说,假设我们要调用同一个项目中不同包中调用其他的模块时,我们设置模块路径时也是从根目录开始寻找,即这里的根目录就是
main.py
所在的位置。 - 方法1:我们用到的是
import
语句,直接导入相应模块。在调用该导入的模块后,使用时我们需要带上其所有的导入语句,并加上相应的方法才能调用。 - 方法2:
from...import...
语句,这里的from后跟了一个包名,这后面的import需要一个模块名。调用时直接用模块名+方法名
即可。 - 方法3:同时
from...import...
语句,有什么不同呢?我们看到,这里的from后跟的是一个具体到模块名位置,而import后则直接导入了一个方法。使用时直接用方法即可。当然我们还可用from 模块名 import *
语句来导入模块中的所有方法。这提供了一个简单的方法来导入一个模块中的所有项目。然而这种声明不该被过多地使用。 - 方法4:是对方法1的补充,
import...as...
语句,import导入了相关的模块后,as对该模块进行重命名。在下面使用时我们直接用重命名的标识符加上方法名即可。 - 方法5:是对方法3的补充,
from...import...as...
语句,我们可以直接对调用的方法进行重命名,使用时直接用重命名后的标识符即可。
- 根据我的摸索,发现了一个问题,就是Python中的模块的路径都是从项目的根目录开始寻找相应的模块的。所以说,假设我们要调用同一个项目中不同包中调用其他的模块时,我们设置模块路径时也是从根目录开始寻找,即这里的根目录就是
-
2.2 各导入语句说明
2.2.1 import语句
-
语法:
import module1[, module2[, module3...]]
-
当解释器遇到import语句,如果模块在当前的搜索路径就会被导入。
-
搜索路径是一个编辑器会先进行搜索的所有目录的列表。而当我们import的时候,Python编辑器就会通过Python的搜索路径来依次从这些目录中去寻找所引入的模块。
-
注意:一个模块只会被导入一次,不管你执行了多少次import,这样可以防止相同的模块一次又一次的执行。
-
现在假设我们要经常用到某个模块中的一个函数时,用import导入后,调用要带上模块名,所以可能有点繁琐,这时候可以用下面的方法解决:
>>> import math >>> pi = math.pi >>> pi 3.141592653589793
- 分析:这里导入了Python内建模块中的
math
模块,假设下面要一直用到pi
这个值,但是每次调用都要用math.pi
来获得,那么就显得有些繁琐,那么我们就可将math.pi
赋值给pi
这个变量,那么接下来在这个函数中使用pi
就可以获得函数值了,变得简便多了。
- 分析:这里导入了Python内建模块中的
2.2.2 from...import... 语句
-
语法:
from module_name import name1[, name2...]
-
这里再以导入math库中的pi为例来进行说明:
>>> from math import pi >>> pi 3.141592653589793
- 分析:可以看到当我们用该语句将函数导入后,我们调用函数时只需要用
pi
即可。这个声明不会将整个math
模块导入到当前命名空间中,它只会将其中的某些函数导入,且调用时只需要用函数名即可。
- 分析:可以看到当我们用该语句将函数导入后,我们调用函数时只需要用
2.2.3 from...import * 语句
-
语法:
from module_name import *
-
用该语法可以将一个模块中的所有函数全部导入到当前的命名空间中。
-
这虽然看起来很简便,当时这种声明不应该被过多的使用,因为容易造成标识符重名现象。
2.2.4 as 语句
-
语法:
-
import module as new_name
-
from module_name import name as new_name
-
-
用两个例子来说明一下:
-
例2.2.4.1:
>>> import math as m >>> m.pi 3.141592653589793
-
例2.2.4.2:
>>> from math import pi as p >>> p 3.141592653589793
-
分析:可以看到
as
语句后面跟的是自己取的名字,就好比将导入的某个函数赋值给了另一个变量一样,可以简化下面调用时的难度。
-
2.3 dir()函数
-
Python内置
dir()
函数可以找到模块内定义的所有函数名称。 -
例2.3.1:
>>> import math >>> dir(math) ['__doc__', '__name__', '__package__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'hypot', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
- 分析:当我们导入了某个模块时,忘记了需要调用的某个函数名时,我们就可以用dir函数来帮我们想起需要的函数名。哈哈,是不是很傻屌,不过感觉还蛮实用的。
-
例2.3.2:
>>> import math >>> dir() # 得到一个当前模块中定义的属性列表 ['__builtins__', '__doc__', '__name__', '__package__', 'math'] >>> del math # 删除了导入的math模块 >>> dir() # 重新用dir函数查看,发现math模块已经删除 ['__builtins__', '__doc__', '__name__', '__package__']
- 分析:如果没有给定参数,那么 dir() 函数会罗列出当前定义的所有名称。
3. 作用域
3.1 引言
- 像java中的private和public这些可以限制变量和方法作用域的关键字,在Python中是如何实现的呢?
- 在一个模块汇总,我们可能定义了很多的函数和变量,但是有的函数和变量我们希望给别人用,有的却只想在自己模块的内部使用,此时就涉及到了作用域的概念。
- Python中,是通过
_
前缀来实现作用域的不同的。
3.2 讲解
- public型,即可被外部调用的:
- 正常的函数和变量名是公开的,可以被外部直接引用,如
abc
,count
,PI
等。
- 正常的函数和变量名是公开的,可以被外部直接引用,如
- 特殊型:
- 像
__xxx__
这种的变量时特殊变量,可以被直接引用,但是有特殊用途,如__author__
,__name__
就是特殊变量,我们自己的变量一般不要用这种变量。
- 像
- private型,只能被模块内部自己调用:
- 类似
_xxx
和__xxx
这样的函数或变量就是非公开的,不能被直接引用,比如_abc
,__count
,__PI
等。
- 类似
- 我们定义函数名时,将外部不需要引用的函数全部定义为private,只有外部需要引用的函数才定义成public。这样我们就可以将内部逻辑用private函数隐藏起来,外部调用时不需要关心函数内部的private函数的内部逻辑,这是一种非常有用的代码封装和抽象的方法。