第5 章函数与模块 锲而舍之,朽木不折;锲而不舍,金石可镂。 ———《荀子·劝学》 在软件开发过程中,经常会在不同的代码位置多次执行相似或完全相同的代码块,这 时就可以将需要反复执行的代码封装为函数或模块,并在需要执行该代码功能的地方进 行函数调用或模块的导入,从而实现代码的复用。利用函数或模块这个特点,在软件开发 过程中就可以把大任务拆分成多个函数或模块,这也是分治法的经典应用,即使复杂问题 简单化,使软件开发像搭积木一样简单。 函数是组织好的可重复使用的用来实现单一或相关联功能的代码段。函数能提高软 件的模块化和代码的重复利用率。 模块是方法的集合,用于有逻辑地组织Python代码段。把相关的代码分配到一个 模块里能让代码更好用、更易懂。简单地说,模块就是一个保存了Python代码的文件。 模块能定义函数、类和变量,模块里也能包含可执行的代码。 Python的默认安装仅包含部分基本或核心模块,启动时也仅加载了基本模块,在需 要时再显式地加载(有些模块可能需要先安装)其他模块,这样可以减少程序运行的压力, 且具有很好的扩展性。 Python可重用的第三方程序代码包括库、函数、模块、类、程序包等,这些可重用代码 统称为库。在Python中使用到的库可以分为以下三类。 (1)Python的内置函数。Python的内置函数是默认安装和加载的基本模块,这些函 数不需要引用库,直接使用即可。Python共提供了68个内置函数。比如,在前面几章介 绍和使用过的print()、内置的数值运算函数、内置的字符串运算函数等。 (2)Python标准库和第三方库(或称扩展库)。Python之所以得到各行业领域工程 师、策划师以及管理人员的青睐,与其庞大的第三方库有很大关系,而且这些库每天都在 以迅猛的速度在增加,大幅度地提高了各行各业软件的开发速度。这些大量的标准库和 第三方库不是Python默认安装和加载的模块,需要导入之后才能使用其中的对象,模块 的文件类型是.py。 标准库内置在Python安装包中,不需要安装,只需导入。受限于安装包的设定大 小,标准库数量不太多,270个左右,安装在Python安装目录的Lib目录下。 第三方库由全球各行业专家、工程师和爱好者开发。第三方库需要先正确安装才能 第5 章 函数与模块1 17 导入。 (3)自定义函数。自定义函数是指程序员在编程过程中,发现某些代码需要重复编 写,而Python内置函数、标准库和第三方库中又没有此类函数,因此需要自己定义的 函数。本 章主要介绍后两类的使用。 5.1 模块的导入和使用 Python标准库和第三方库都需要先导入才能使用。 Python中导入模块的方法主要有import语句和from…import语句两种形式。 1.import语句 导入模块的语法格式如下: import 模块1[, 模块2[,… 模块N] 使用模块的语法格式如下: 模块名.函数名(参数) 例如: >>> import math >>> math.sqrt(9) 3.0 >>> math.sin(2) 0.9092974268256817 2.from…import语句 语法格式一: from 模块名import 函数名或变量名1[,函数名或变量名2[, … 函数名或变量名N]] 语法格式二: from 模块名import * 说明: 语法格式一是从模块中导入指定的模块成员。 语法格式二是把模块的所有内容全都导入到当前的命名空间。这种导入方式可以减 少查询次数,提高访问速度,同时也减少了程序员需要输入的代码量,而不需要使用模块 名作为前缀。这种导入模块方式虽然写起来比较省事,可以直接使用模块中的所有函数 和对象而不需要再使用模块名作为前缀,但一般并不推荐使用。因为如果多个模块中有 同名的对象,这种方式将会导致只有最后一个导入的模块中的同名对象是有效的,而之前 导入的模块中的该同名对象无法访问。 使用模块的语法格式如下: 1 18 大学计算机———Python 程序设计基础 函数名(参数) 例如: >>> from math import sqrt,sin >>> sqrt(9) 3.0 >>> sin(2) 0.9092974268256817 例5-1 导入calendar模块,用户输入想要查询的年和月后,显示该月的日历。 【程序5-1.py】 1 from calendar import month 2 yy = int(input("输入年份: ")) 3 mm = int(input("输入月份: ")) 4 print(month(yy,mm)) 【运行结果】 输入年份: 2019 输入月份: 7 July 2019 Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 另外,如果想使用已有的Python文件,也只需在另一个程序文件中执行导入语句 即可。 例5-2 已知eg1.py中有一个名为f的函数,如下所示。编写程序,在另外一个程 序中调用eg1.py中的f函数。 【eg1.py】 1 def f(): 2 print('eg1.py is OK!!!') 【程序5-2.py】 1 from eg1 import * 2 print("调用eg1 中的f 函数") 3 f() 【运行结果】 调用eg1 中的f 函数 eg1.py is OK!!! 第5 章 函数与模块1 19 .................................................................................. ........ .................................................................................. ........ 说明:在用import语句导入模块时,最好按照这样的顺序依次导入,即Python标 准库模块→Python扩展库模块→自定义函数。 5.2 Python标准库 Python标准库是Python安装的时候默认自带的标准库。Python标准库无须安装。 Python标准库中有众多的库,这里介绍其中常用的三个库。 5.2.1 random 库 random 库是使用随机数的Python标准库。 Python中随机数的生成基于随机数种子,根据输入的种子,利用算法生成一系列的 随机数。random 库的常用函数有9个,见表5-1所示。 表5-1 random 库的常用函数 函 数描 述 seed(a=None) 初始化随机数种子,默认值为当前系统时间,例如: > > > random.seed(10)#产生种子10对应的序列 random() 生成一个[0.0,1.0)的随机小数,例如: > > > random.random() 0.5714025946899135 randint(a,b) 生成一个[a,b]的随机整数,例如: > > > random.randint(10,100) 84 getrandbits(k) 生成1kb长的随机整数,例如: > > > random.getrandbits(16) 37885 randrange(m,n[,k]) 生成一个[m,n)的以k为步长的随机整数,例如: > > > random.randrange(10,100,10) 90 uniform(a,b) 生成一个[a,b]的随机小数,例如: > > > random.uniform(10,100) 16.848041210321334 choice(seq) 从序列类型(字符串、列表、元组)中随机选择一个元素,例如: > > > random.choice([1,2,3,4,5,6,7,8,9]) 8 续表 1 20 大学计算机———Python 程序设计基础 函 数描 述 shuffle(seq) 将序列类型(字符串、列表、元组)中元素随机排列,返回打乱顺序后的 序列,例如: > > > s=[1,2,3,4,5,6,7,8,9] > > > random.shuffle(s) > > > s [9,4,6,3,5,2,8,7,1] sample(pop,k) 从组合类型(字符串、列表、元组、集合)中随机选取k个元素,以列表 类型返回,例如: > > > random.sample("1234567",3) [1' ',4' ',7' '] > > > random.sample({1,2,3,4,5,6},2) [1,4] 例5-3 随机生成一个四位验证码。四位验证码中的每位元素可以是3种情况:数 字0~9、大写字母A~Z或小写字母a~z。 【程序5-3.py】 1 import random 2 checkcode = '' 3 for i in range(4): #每循环一次产生一位验证码元素 4 n = random.randrange(0, 3) #生成随机数0~2(因为有三种情况) 5 if n == 0: 6 tmp = chr(random.randrange(65, 91)) #数字65~90 对应字母A~Z 7 elif n == 1: 8 tmp = chr(random.randrange(97, 123)) #数字97~122 对应字母a~z 9 else: 10 tmp = random.randrange(0, 10) #生成随机数字0~9 11 checkcode += str(tmp) 12 print(checkcode) 【运行结果】 8ZjL 5.2.2 time库 time库是Python中处理时间的标准库,主要用于获取系统时间,提供系统级精确计 时功能,以便进行程序性能分析。 1.时间处理 时间处理主要包括如下4个函数。 (1)使用time.time()获取当前时间戳。 第5 章 函数与模块1 21 时间戳是指格林尼治时间1970年01月01日00分00秒(北京时间1970年01月01 日08时00分00秒)起至现在的总秒数。 Python获取时间的常用方法是,先得到时间戳,再将其转换成想要的时间格式。 例如: >>> import time >>> time.time() 1564450927.1466367 (2)使用time.gmtime([secs])把一个时间戳(按秒计算的浮点数)转换为struct_ time对象。 日期、时间是包含许多变量的,所以在Python中定义了一个元组对象struct_time将 所有这些变量组合在一起,包括4位数年、月、日、小时、分钟、秒等,其元素构成见表5-2 所示。 表5-2 struct_time对象的元素构成 下标属性值 0 tm_year 年,4位整数 1 tm_mon 月,1~12 2 tm_mday 日,1~31 3 tm_hour 小时,0~23 4 tm_min 分,0~59 5 tm_sec 秒,0~61(60或61是闰秒) 6 tm_wday 星期,0~6(0是周一) 7 tm_yday 该年的第几天,1~366 8 tm_isdst 是否夏令时,0为否、1为是、-1为未知 例如: >>> time.gmtime() time.struct_time(tm_year = 2019, tm_mon = 7, tm_mday = 30, tm_hour = 2, tm_min = 12, tm_sec = 57, tm_wday = 1, tm_yday = 211, tm_isdst = 0) (3)使用time.localtime([secs]把一个时间戳(按秒计算的浮点数)转换为本地时间 的struct_time对象。例如: >>> time.localtime() time.struct_time(tm_year = 2019, tm_mon = 7, tm_mday = 30, tm_hour = 9, tm_min = 53, tm_sec = 4, tm_wday = 1, tm_yday = 211, tm_isdst = 0) (4)使用time.ctime(secs)把一个时间戳(按秒计算的浮点数)转换为对应的易读字 1 22 大学计算机———Python 程序设计基础 符串表示。例如: >>> time.ctime() 'Tue Jul 30 10:13:18 2019' 2.时间格式化 时间格式化主要包括如下3个函数。 (1)使用time.mktime(t)将struct_time对象t转换为时间戳,注意t为当地时间。 该函数相当于time()的逆函数。例如: >>> time.mktime(time.localtime()) 1564452132.0 (2)使用time.strftime(format[,t])将对象t格式化输出。strftime()的格式化控制 符见表5-3所示。 表5-3 strftime()的格式化控制符 格式化字符串含 义值 %Y 年份0001~9999,例如1970 %m 月份01~12,例如10 %B 月名January~December,例如April %b 月名缩写Jan~Dec,例如Apr %d 日期01~31,例如23 %A 星期Monday~Sunday,例如Wednesday %a 星期缩写Mon~Sun,例如Wed %H 小时(24小时制) 00~23,例如10 %I 小时(12小时制) 01~12,例如5 %p 上午/下午AM,PM,例如PM %M 分钟00~59,例如22 %S 秒00~59,例如16 例如: >>> time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()) 'Tue, 30 Jul 2019 07:27:56 +0000' (3)使用time.strptime(string[,format])提取字符串中的时间来生成struct_time 对象,与strftime()完全相反。例如: >>> time.strptime('2019-7-30 10:30:35',"%Y-%m-%d %H:%M:%S") time.struct_time(tm_year = 2019, tm_mon = 7, tm_mday = 30, tm_hour = 10, tm_min = 30, tm_sec = 35, tm_wday = 1, tm_yday = 211, tm_isdst = -1) 第5 章 函数与模块1 23 3.计时 计时主要包括如下两个函数。 (1)使用time.sleep(t)函数推迟调用线程的运行,t是指推迟执行的秒数。例如 time.sleep(5)表示推迟5秒钟调用线程。 (2)使用time.perf_counter()返回系统运行的精准时间。 例5-4 测试一下当前计算机运行某程序的速度。 【程序5-4.py】 1 from time import* 2 d1 = perf_counter() #返回计时器的精准时间(系统的运行时间) 3 for i in range(1,10000000+1): 4 pass 5 d2 = perf_counter() 6 print("程序运行时间是:{}秒".format(d2-d1)) 【运行结果】 程序运行时间是:0.40451200419390826 秒 5.2.3 datetime库 datetime模块在支持日期和时间算法的同时,实现的重点放在更有效的处理和格式 化输出。例如: >>> from datetime import date >>> now = date.today() >>> now datetime.date(2019, 7, 31) >>> now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.") '07-31-19. 31 Jul 2019 is a Wednesday on the 31 day of July.' 5.2.4 tkinter库 tkinter是Python中可用于构建GUI(GraphicalUserInterface,图形化用户界面,也 称为图形用户接口)的众多工具集之一。 1.tkinter编程 由于tkinter是内置到Python 的安装包中,只要安装好Python 之后,就能导入 tkinter库,而且IDLE也是用tkinter编写而成,对于简单的图形界面tkinter能应付自 如。例如: >>> from tkinter import * >>> window = Tk() >>> window.mainloop() 1 24 大学计算机———Python 程序设计基础 以上代码可以显示一个空白窗口。可以将其看成是应用程序的最外层容器,创建其 他插件的时候就需要用到它。如果关闭屏幕上的窗口,则相应的窗口对象就会被销毁。 所有的应用程序都只有一个主窗口;此外,还可以通过TopLevel小插件来创建其他的窗 口。tkinter的小插件包括Button、Canvas、Checkbutton、Entry、Frame、Label、Listbox、 Menu、Message、Menubutton、Text、TopLevel等。 2.tkinter组件 tkinter的提供各种控件,如按钮、标签和文本框等,见表5-4所示。 表5-4 tkinter组件 控 件描 述 Button 按钮控件,在程序中显示按钮 Canvas 画布控件,显示图形元素如线条或文本 Checkbutton 多选框控件,用于在程序中提供多项选择框 Entry 输入控件,用于显示简单的文本内容 Frame 框架控件,在屏幕上显示一个矩形区域,多用来作为容器 Label 标签控件,可以显示文本和位图 Listbox 列表框控件,Listbox是用来显示一个字符串列表给用户的 Menubutton 菜单按钮控件,用于显示菜单项 Menu 菜单控件,显示菜单栏、下拉菜单和弹出菜单 Message 消息控件,用来显示多行文本,与Label类似 Radiobutton 单选按钮控件,显示一个单选的按钮状态 Scale 范围控件,显示一个数值刻度,用于输出限定范围的数字区间 Scrollbar 滚动条控件,当内容超过可视化区域时使用,如列表框 Text 文本控件,用于显示多行文本 Toplevel 容器控件,用来提供一个单独的对话框,与Frame类似 Spinbox 输入控件,与Entry类似,但它可以指定输入范围值 PanedWindow 窗口布局管理的插件,可以包含一个或者多个子控件 LabelFrame 简单的容器控件。常用于复杂的窗口布局 tkMessageBox 用于显示应用程序的消息框 3.标准属性 标准属性也就是所有控件的共同属性,如大小、字体和颜色等,见表5-5所示。 表5-5 标准属性 属 性描 述 Dimension 控件大小 续表 第5 章 函数与模块1 25 属 性描 述 Color 控件颜色 Font 控件字体 Anchor 锚点 Relief 控件样式 Bitmap 位图 Cursor 光标 4.几何管理 tkinter控件有特定的几何状态管理方法,管理整个控件的区域组织,包括三种几何 管理方法:pack()(包装)、grid()(网格)和place()(位置)。 pack()是三种布局管理中最常用的。另外两种布局需要精确指定控件具体的显示位 置,而pack()布局可以指定相对位置,精确的位置由pack()系统自动完成。pack()几何 管理采用块的方式组织配件,在快速生成界面设计中广泛采用,若干组件简单的布局,采 用pack()的代码量最少。pack()几何管理程序根据组件创建生成的顺序将组件添加到 父组件中去。 grid()几何管理采用类似表格的结构组织配件,使用起来非常灵活,用其设计对话框和 带有滚动条的窗体效果最好。grid()采用行列确定位置,行列交汇处为一个单元格。每一列 中,列宽由这一列中最宽的单元格确定。每一行中,行高由这一行中最高的单元格决定。 place()布局管理可以显式地指定控件的绝对位置或相对于其他控件的位置。要使 用place()布局,调用相应控件的place()方法就可以了。所有tkinter的标准控件都可以 调用place()方法。 例5-5 从右向左布局按钮。 【程序5-5.py】 1 from tkinter import * 2 root = Tk() #创建根窗口 3 bt1 = Button(text = "button1") #创建按钮1 4 bt1.pack(side = 'right') #显示按钮1,靠右 5 bt2 = Button(text = "button2") #创建按钮1 6 bt2.pack(side = 'top') #显示按钮2,置顶 【运行结果】 如图5.1所示。 例5-6 通用消息对话框的使用。 【程序5-6.py】 1 import tkinter 2 from tkinter import messagebox