大家好,上一节课,我们学习了python的函数,我们由此知道Python编程不仅仅可以通过一些基本的对象(如常量和变量、运算符和表达式)及流程控制语句,来编写代码实现一些简单的应用,还能通过创建函数,构建更加复杂的程序结构。
当然,我们学会了把函数嵌入到一般的程序流程中,纵然可以解决一些相对复杂的问题,甚至实现了简单的代码重用。
但是,这与其他高级语言相比,还是远远不够的。如果我们就此止步的话,当我们面对一个大型的复杂的应用需求的时候,我们是很难使用一个或几个应用程序来搞定它的。所以,Python还有没有更高级的工具?神奇如Python,当然是有的。
比函数更高级的工具,应该具备以下两个属性:
(1)它的格局应该更高,也就是说要能有利于我们搭建一个应用系统的架构。
(2)它能够让我们对已经封装好的函数,在系统的任何地方都能够方便地调用,最大限度地实现代码块的重用。
一切所谓的智慧最终都是为了降低熵的增加。
实现了这两条,就不仅能够减少程序员的重复劳动,更重要的是降低系统的复杂度。这个所谓的“高级工具”就是我们今天要介绍给大家的Python的模块。
Pyhton模块(Modules),是Python最高级别的程序组织单元,它能将程序代码和数据封装起来,以便重用。
本质上讲,每一个python文件都是一个python的模块。并且,模块在导入了其他模块之后,就可以直接使用被导入模块所定义的变量和函数。
所以,看起来又没什么新东西啊!
PS:不错,在福尔摩斯说出谜底之后,华生从来都是不屑的。
基本上,只要我们学会了模块导入的方法,我们就能方便地应用模块的概念了。
模块的导入应用通常有以下两种方式:
1、import 语句
2、from ... import 语句
这就像其他很多优秀的面向对象的编程语言一样,Python也引进了这个更高级别的重要对象,它能将一些可重用的函数集成到一起,形成一个Python文件。然后,它可以被任何程序导入,并使用其中的任何一个函数。
这样的架构,让我们的编程效率大大提高。由此,也引入了一个重要的编程理念,那就是凡是遇到需要构建任何一个解决问题的方法(解决方案)时,我们都要努力地把它“封装”到可重用的函数中,这样,我们就有机会在下一次遇到相同或类似的问题的时候,实现代码的重用。这是非常重要的编程思想。
1、import 语句
首先,我们创建一个空的模块文件:module_1.py,并添加如下代码。
#示例 module_1.py
def func_sun(x):
if x==1:
print('草原上升起不落的太阳!')
else:
print('太阳下山了,喜洋洋咯!')
说明:该模块文件包含一个函数,它有一个形参x,并根据该参数接收到的值是否等于1,来决定它向屏幕显示的内容。
再创建一个python应用程序:module_app_1.py(其实,还是一个python文件,必要时你也可以把它当做一个模块文件)
#示例 module_app_1.py
import modlue_1
a=1
modlue_1.func_sun(a)
说明:这个python程序,通过import语句,导入了模块文件module_1,并且调用了它的函数func_sun(),同时向函数传递了一个实参a的值。
OK,import语句的应用就是这个样子的,你学会了吗?
2、from ... import 语句
下面,我们来修改一下模块文件module_1.py和程序文件module_app_1.py
#示例 修改后的module_1.py
def func_sun(x):
if x==1:
print('草原上升起不落的太阳!')
else:
print('太阳下山了,喜洋洋咯!')
def func_month():
print('月亮代表我的心!')
说明:模块文件包新增一个函数,这让我们更能看到一个模块文件的意义:它可以是若干个可重用的函数的集合。事实上,函数的集合才能让模块具有更大的意义。
#示例 修改后的module_app_1.py
a=1
b=2
if a==b:
from modlue_1 import func_sun
func_sun(a)
else:
from module_1 import func_month
func_month()
说明:其实,重点在这里:我们使用from...import语句,直接导入了模块文件module_1的函数,然后就像本地(本应用程序文件中)的函数一样使用它。
警告:虽然python支持from...import 语句,但是,为了避免在你的程序中出现名称冲突,同时也为了使程序更加易于阅读,我们仍然应该尽量避免这样使用模块文件,而选择简单使用import语句显然更好一些。
3、Python的内置模块
正如python有许多内置变量和函数一样,python也有许多内置模块,例如os模块、sys模块、hashlib模块、time & datetime模块,等等。这些内置模块的封装,为我们实现应用程序的开发提供了极大的便利。
例如,sys模块包含如下内置函数(部分)
sys.argv 命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit(0)
sys.version 获取Python解释程序的版本信息
sys.maxint 最大的Int值
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
4、sys.path
这里,提醒一个我们使用python模块的一个重要问题:模块文件的路径问题。如果路径设置不正确,我们将无法正常使用模块文件及其内部的变量与函数资源。
对于python内置模块,它自然知道怎么去寻找模块的位置,因为我们在下载安装Python时已经配置好了。但是,如果我们自定义模块,我们就要特别注意,在导入模块时,python的解释器将从sys.path变量所提供的目录中进行搜索。如果找到了对应的模块,则该模块中的语句将开始运行,并能为你所使用。
PS:我们调用sys.path时,会发现sys.path的第一段字符串是空的,这一空字符串代表的是当前目录,它也是sys.path的一部分。
sys.path与PYTHONPATH 环境变量是一致的。这意味着当前目录下的模块,你可以直接导入。否则,你必须将你的模块文件放置在sys.path所列出的目录中,你也可以通过修改PYTHONPATH 环境变量,来添加你的模块文件所在的目录路径。
5、dir 函数
python内置的 dir() 函数能够返回由对象所定义的名称列表。
dir()数接受参数。 如果参数是模块名称,函数将返回这一指定模块的名称的列表。 如果没有提供参数,函数将返回当前目录下的所有模块的名称列表。
# 给出 sys 模块中的属性名称
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'b', 'func_sun', 'i', 'sys']
包
理解了函数和模块的概念,我们似乎要跃跃欲试,开始大显身手了。
且慢!
我们当下学习的虽然只是一个入门的课程,但是,至此你确实可以写出不少的甚至有些复杂应用程序。那么,我们也该开始意识到,面对一个应用需求,该如何组织这个应用程序项目的基本架构?因此,我们需要了解包(Packages)的概念。
包是一种能够方便地分层组织模块的方式,更具体的说,它就是一个文件夹:它包含了模块与一个特殊的 __init__.py文件。这个特殊文件是这个包的一个标识,它通常由IDE在创建包文件夹时自动创建的一个没有内容的空文件。但是,缺少该文件的文件夹就不能称之为包了。
所以,简单地理解就是:包含了一个__init__.py文件的文件夹,就是一个包,它能清晰地分层组织模块文件。
例如:你想创建一个名为“ab”的包,其中还包含着 “a”、“b”等其它子包,同时这些子包都包含了诸如“a1”、 “b1”等模块。
那么,这个包文件夹的结构如下:
- ab/
- __init__.py
- a/
- __init__.py
- a1/
- __init__.py
- m_a.py
- b/
- __init__.py
- b_1/
- __init__.py
- m_b.py
小结
这一节,我们学习了Python的模块。如同对函数的理解一样,模块不仅更好地解决了我们对于程序代码的重用问题,模块还是一种应用程序架构的重要组织形式,它让我们的应用程序的组织架构又上升了一个维度。事实上,Python 所附带的标准库就是这样一组有关包与模块的重要例子。
各位学友,到此,Python的基础入门知识我们已经完成了第一阶段的学习任务。请大家尝试运用所学,去解决一些日常需求,比如,有一个随机的数字字符串,我们如何把它们由小到大地排列起来呢?或者,面对1 — 10000的连续整数,如何把它们累加求和呢?试试看吧,说不定你能做到呢?
预告
下节课,我们要接触一个非常重要的概念:数据结构。可以说它是python应用之所以显得强大的一个重要原因,也是构成我们python入门知识结构的一块非常重要的积木。