Logo

郎哥编程

模块与包

2020-12-20 206

模块是一组函数和代码的组合,模块实际上是一个包含了函数定义和代码的文件,文件名就是模块名称加上后缀py,前面课程案例编写的py文件都属于模块。

包用来组织组织模块并提供名称层次结构,可以把包看成是电脑磁盘中的文件目录,并把模块看成是目录中的文件。与电脑磁盘的文件目录一样,包通过层次结构进行组织,在包之内除了一般的模块,还可以有子包。

使用模块分解程序功能

平时我们在解决一些复杂问题时,会把一个复杂的问题分解成多个子问题,先逐个解决这些子问题,当这些子问题解决后,复杂的问题自然就得到了解决。

例如:假如你要在家做一顿丰盛的晚餐,你可能会安排人去采购食材、安排另外的人备菜,你负责掌勺。我们如果把做一顿丰盛的晚餐作为一个复杂问题,那么采购食材、备菜、掌勺就是这个复杂问题的子问题,当采购食材、备菜、掌勺这些问题得到解决后,做一顿丰盛的晚餐这个大问题自然就得到了解决。

10.png

把复杂的问题分解成多个子问题就是分而治之的思想,分而治之的思想同样也可以使用到编程过程中。对于复杂的程序,可以对程序的功能进行分解,将程序的功能分解成多个子功能,从而达到将复杂问题进行简化的目的。

案例1:编写一个面积计算器程序,用于帮助学生理解平面几何图形的边长与面积的关系。程序可以计算长方形、正方形、平行四边形、三角形的面积。

面积计算器可以分解为计算长方形的面积、计算正方形的面积、计算平行四边形的面积、计算三角形的面积四个子功能,每个子功能是一个独立的模块。

11.png

一个Python程序由一个模块或多个模块组成,每个模块就是一个代码文件。在这些模块中,只有一个是主模块,该主模块将被python解释器直接执行模块中的代码,其它模块为功能模块,功能模块只有被主模块的代码调用后才会执行。

模块在Python中也是对象,模块对象有一个属性是__name__,表示模块的名称,__name__是可以被修改的。当直接运行模块时,模块的__name__属性值是“__main__”,若该模块被导入其它程序,模块的__name__属性值是模块名称。因此可以通过模块的__name__属性来区分模块是主模块还是功能模块。

按照功能划分,面积计算器程序共有五个模块,主模块为main.py,计算长方形面积的模块为rectangle.py,计算正方形面积的模块为square.py,计算平行四边形面积的模块为paraller.py,计算三角形面积的模块为triangle.py。

12.png

模块划分完成后,就可以开始编写每个模块代码了。

(1)计算长方形面积模块代码——rectangle.py

# 定义函数area
def area():
    while(True):
        # 输出提示信息
        a = input("请输入长方形的长(整数):")
        # 判断a是否是整数或小数
        if a.isdigit():
            # 输出提示信息  
            b = input("请输入长方形的宽(整数):")
            if b.isdigit():
                S = int(a) * int(b)
                return S
            else:
                print("输入错误,请重新输入")
        # 提示学生输入错误
        else:
            print("输入错误,请重新输入")

代码解读

代码定义了area函数,用于计算长方形的面积。在area函数内部使用了while循环,当学生输入的内容不是整数时,函数会提示学生输入错误,直至学生输入正确的长方形的长和宽。函数计算长方形的面积,并返回面积。

(2)计算正方形面积模块代码——square.py

# 定义函数area
def area():
    while(True):
        # 输出提示信息
        a = input("请输入正方形的边长(整数):")
        # 判断a是否是整数或小数
        if a.isdigit():
            S = int(a) * int(a)
            return S
        # 提示学生输入错误
        else:
            print("输入错误,请重新输入")

代码解读

计算正方形面积的代码和计算长方形面积的代码基本相同,在编写代码时,可以把rectangle.py的代码复制过来,在rectangle.py代码的基础上修改即可。

(3)计算平行四边形面积模块代码——paraller.py

# 定义函数area
def area():
     while(True):
        # 输出提示信息
        a = input("请输入平行四边形的底(整数):")
        # 判断a是否是整数或小数
        if a.isdigit():
            # 输出提示信息  
            h = input("请输入平行四边形的高(整数):")
            if h.isdigit():
                S = int(a) * int(h)
                return S
            else:
                print("输入错误,请重新输入")
        # 提示学生输入错误
        else:
            print("输入错误,请重新输入")

代码解读

编写代码一定要注意语句的缩进对齐,同一层次的语句左侧要对齐。内层语句要比外层语句缩进一定数量的空格,建议都是四个空格。

(4)计算三角形面积模块代码——triangle.py

# 定义函数area
def area():
    while(True):
        # 输出提示信息
        a = input("请输入三角形的底(整数):")
        # 判断a是否是整数或小数
        if a.isdigit():
            # 输出提示信息  
            h = input("请输入三角形的高(整数):")
            if h.isdigit():
                S = int(a) * int(h) / 2
                return S
            else:
                print("输入错误,请重新输入")
        # 提示学生输入错误
        else:
            print("输入错误,请重新输入")

代码解读

当while循环条件设置为True时,一定要在循环体有退出循环机制。当学生输入正确的底和高后,函数计算三角形的面积,并使用return语句返回面积,函数执行结束,循环自然就退出了。

使用import语句导入模块

案例1还需要编写主模块代码,在主模块中需要调用另外四个模块的函数,来完成不同几何图形的面积计算。不同于Python内置函数的调用,主模块要调用另外四个模块的函数,必须要导入这四个模块。

导入模块有两种方式:一种方式是使用import语句;一种方式是使用带from子句的import语句。

使用import语句导入模块

import语句用于导入外部模块,import语句的基础语法如下:

import  module [as identifier] (, module [as identifier])

其中module是模块名称,模块名称一般是模块文件的名称去掉扩展名py;[as identifier]是可选项,为导入的模块命名一个别名,as是import语句的一部分,identifier是别名,如果模块名称之后带有as,则跟在as之后的名称将直接绑定到所导入的模块;(, module [as identifier]) 表示可以导入多个模块,每个模块之间用英文逗号分隔。

模块的别名一是起到简化模块名称的作用,二是导入多个模块时,用于区分名称重复的模块。

例如:

# 导入rectangle.py模块
import rectangle 
# 导入rectangle.py模块,该模块别名为rect
import rectangle as rect
# 导入rectangle.py、triangle.py模块
import rectangle as rect, triangle as angle
带from子句的import语句
import语句也可以带from子句,带from子句的基础语法如下:
from relative_module import identifier [as identifier]
                     (, identifier [as identifier])

可以导入指定模块的子模块或模块内部的属性和方法,其中relative_module是导入的模块名称;identifier是子模块名称或模块内部的属性和方法名称,[as identifier]是可选项,为导入的模块内容命名一个别名;(, identifier [as identifier])表示可以从指定的模块中导入多个子模块或模块内部的属性和方法,每个导入项之间用英文逗号分隔。

例如:

>>> from sys import platform as p,version as v
>>> print(p,v)
win32 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:37:02) [MSC v.1924 64 bit (AMD64)]
>>>

案例代码从Python的sys模块导入了platform和platform属性,并别名为p和v。sys模块是Python内置的系统模块,可以获取操作系统信息或执行一些系统操作。platform属性表示当前使用的操作系统,version表示当前使用的Python版本。

模块的搜索路径

当导入一个模块时,Python解释器会搜索要导入的模块文件,如果在搜索路径下没有找到要导入的模块文件,会引发 ModuleNotFoundError异常。

Python搜索模块的路径是由四部分构成的:程序的主目录、PATHONPATH环境变量、标准链接库目录、扩展名为pth的路径配置文件,这四部分的路径都存储在sys.path 列表中。

(1)程序的主目录

程序的主目录是指包含主模块的目录,Python首先会在主目录中搜索模块,若所有模块都在主目录中,所有的导入都会自动完成,而不需要单独配置模块路径。

(2)PATHONPATH环境变量

PATHONPATH是Windows系统的环境变量,在Windows系统中可以设置PATHONPATH环境变量,将项目存储模块文件的路径添加到PATHONPATH环境变量。

(3)标准链接库目录

标准链接库目录是Python安装第三方库的目录,这些目录是Python解释器的默认搜索目录。

(4)扩展名为pth的路径配置文件

如果不设置PATHONPATH环境变量,也可以用记事本创建一个扩展名为pth的路径配置文件,该文件每一行都是一个有效的目录,Python会读取路径文件中的内容,每行都作为一个有效的目录,加载到模块搜索路径列表中。

例如下面的文件内容:

d:\pythoncode\module\lib
d:\pythoncode\book\lib

该文件要放置到Python的安装目录或标准库所在的目录,才能被Python自动读取。文件放置的目录可以通过下面的Python代码查看:

>>> import site
>>> site.getsitepackages()
['C:\\python', 'C:\\python\\lib\\site-packages']
>>>

site模块用于添加指定路径到Python的搜索路径,该模块在Python运行时会自动加载,并读取扩展名为pth的路径配置文件。

导入模块后,可以使用模块名称或别名来访问模块内部的对象或函数,访问方式如下所示:

13.png

包也属于模块,包是一种特殊的模块。可以把包看成是文件系统中的目录,并把模块看成是目录中的文件,与文件系统一样,包通过层次结构进行组织,在包之内除了一般的模块,还可以有子包。

例如,以下文件系统布局定义了一个最高层级的 parent 包和三个子包:

16.png

图中的parent是顶层包,parent包下有one、two、three三个子包,有pa.py模块文件;one包下有onea.py模块文件,two和three包内没有模块文件。

__init__.py是包的初始化文件,如果让目录文件系统中的目录称为包,在目录下必须有__init__.py文件,否则该目录不是包,__init__.py 文件可以包含与任何其他模块中所包含的 Python 代码相似的代码,也可以是一个空的文件。

导入parent.one 将隐式地执行 parent/__init__.py 和 parent/one/__init__.py。 后续导入 parent.two 或 parent.three 则将分别执行 parent/two/__init__.py 和 parent/three/__init__.py。

 子包名与其父包名以“.”符号分隔,parent.one表示parent包的子包one,parent.one.pa表示parent包的子包one包内的模块pa。

导入包的语法和导入模块的语法相同,具体导入方法参考下面的案例代码:

# 导入one包内的onea模块
import parent.one.onea as one
# 导入one包内的onea模块
from parent.one import onea as one

编写案例程序的主模块

模块代码编写完成后,开始程序主模块的编写。

程序支持长方形、正方形、平行四边形和三角形的面积计算,程序启动后,会进入选择状态,用户可以选择其中的一个状态,该状态对应计算一个几何图形的面积,面积计算完成后,程序会再次进入选择状态。

选择状态为1、2、3、4,状态1计算长方形的面积,状态2计算正方形的面积,状态3计算平行四边形的面积,状态4计算三角形的面积。

17.png

程序的具体流程为:

(1)   程序输出提示信息,要求学生选择状态,或者输入quit退出程序;

(2)   学生选择状态,程序调用状态对应的模块来计算几何图形的面积;

(3)   面积计算完成,程序会再次进入选择状态,等待学生的选择;

(4)   如果学生输入quit,退出程序。

18.png

主模块代码:

# 导入模块
import rectangle as rect
import square as sq
import paraller as pa
import triangle as tr
 
# 程序入口
if __name__ == '__main__':
       
    while(True):
        # 输出提示信息
        print("-------欢迎使用面积计算器------\n")
        print("按下数字1键:计算长方形面积\n")
        print("按下数字2键:计算正方形面积\n")
        print("按下数字3键:计算平行四边形面积\n")
        print("按下数字4键:计算三角形面积\n")
        print("输入quit,退出程序\n")
 
        # 获取学生的输入
        num = input("请输入:")
       
        # 输入数字1?
        if num == "1":
            print("长方形的面积为:" + str(rect.area()))
           
        # 输入数字2?
        elif num == "2":
            print("正方形的面积为:" + str(sq.area()))
 
        # 输入数字3?
        elif num == "3":
            print("平行四边形的面积为:" + str(pa.area()))
 
        # 输入数字4?
        elif num == "4":
            print("三角形的面积为:" + str(tr.area()))
 
        # 输入quit?
        elif num == "quit":
            break

使用import语句导入计算长方形、正方形、平行四边形和三角形面积的模块文件。

在while循环体内,首先输出提示信息,提示学生按下不同的数字键,选择计算对应的几何体面积,也可以输入quit退出程序。

然后使用input函数获取学生的输入,使用多重条件结构来判断学生的输入。如果输入的是1、2、3、4数字字符,分别调用对应的模块函数来计算几何体的面积。如果输入的是quit,调用break语句退出循环,程序结束。

上机操作

编写完整的课程案例,要求如下:

(1)项目目录结构及文件名称如下图所示:

19.png

(2)添加或编辑Windows系统环境变量PYTHONPATH,将项目lib目录的物理路径添加到PYTHONPATH。

代码在线纠错(通义千问 qwen-max)

支持粘贴多个代码文件,提交后由阿里云通义千问自动分析代码漏洞、语法错误、逻辑问题并给出修改建议。
您已解锁 AI 代码纠错功能,可正常使用!

评论区

登录 后发表评论
暂无评论