《Python网络安全项目实战》项目2 Python基础练习

news2024/12/23 7:00:48

在这里插入图片描述

《Python网络安全项目实战》项目2 Python基础练习

  • 项目2 Python基础练习
    • 任务2.1 使用数据类型
      • 2.1.1 输出
      • 2.1.2 输入
      • 2.1.3 数字
      • 2.1.4 字符串
      •  相关知识
      •  任务评价
      •  任务拓展
    • 任务2.2 使用组合数据类型
      • 2.2.1 列表
      • 2.2.2 元组
      • 2.2.3 集合
      • 2.2.4 字典
      •  相关知识
      •  任务评价
      •  任务拓展
    • 任务2.3 使用控制结构
      • 2.3.1 if 语句
      • 2.3.2 while 循环
      • 2.3.3 for循环
      •  相关知识
      •  任务评价
      •  任务拓展
    • 任务2.4 使用函数
      • 2.4.1 函数
      • 2.4.2 函数参数的传递
      • 2.4.3 函数的Lambda 形式
      • 2.4.4 文档字符串
      • 2.4.5 函数注解
      •  相关知识
      •  任务评价
      •  任务拓展
    • 任务2.5 使用模块
      • 2.5.1 模块
      • 2.5.2 标准模块
      • 2.5.3 包
      •  相关知识
      •  任务评价
      •  任务拓展
    • 项目评价

项目2 Python基础练习

Python是一门完整的编程语言;与 Shell 脚本或批处理文件相比,它为编写大型程序提供了更多的结构和支持。并且作为一门高级语言,它内置支持高级的数据结构类型,例如:灵活的列表和字典。Python 允许你将程序分割为不同的模块,以便在其他的 Python 程序中重用。Python 内置提供了大量的标准模块,你可以将其用作程序的基础,或者作为学习 Python 编程的示例。下面的网址含有大量的Python基础学习资料和操作指导,可以用来配合本项目的学习。
http://www.pythondoc.com/
http://www.runoob.com/python3/python3-tutorial.html

项目目标:
熟悉Python的关键要素:
 数据类型
 组合数据类型
 控制结构
 函数
 模块

任务2.1 使用数据类型

任务描述
公司接到一个项目需要使用Python进行编程,项目经理布置任务需要我们小组进行编程的准备并写出个例子程序。请大家和我一起熟悉python数据类型的使用,进行准备并使用Python编程。
任务分析
Python具有高级的内置数据类型,比如灵活的数字和字符串。由于python提供了更为通用的数据类型,Python 操作数据会更简单明了。
 输出
 输入
 数字
 字符串
任务实施

2.1.1 输出

用print加上字符串,就可以向屏幕上输出指定的文字。比如输出“hello world”,如图2-1-1所示。
在这里插入图片描述

图2-1-1输出
print语句也可以跟上多个字符串,用逗号“,”隔开,就可以连成一串输出,如图2-1-2所示。
在这里插入图片描述

图2-1-2 多个字符串
print会依次打印每个字符串,遇到逗号“,”会输出一个空格,因此,输出的字符串是这样拼起来的,如图2-1-3所示。
在这里插入图片描述

图2-1-3输出的字符串
print也可以打印整数,或者计算结果,如图2-1-4所示。
在这里插入图片描述

图2-1-4 整数
因此,我们可以把计算100 + 200的结果打印得更漂亮一点,如图2-1-5所示。

在这里插入图片描述

图2-1-5 打印结果
注意,对于100 + 200,Python解释器自动计算出结果300,但是,'100 + 200 ='是字符串而非数学公式,Python把它视为字符串,请自行解释上述打印结果。

2.1.2 输入

现在,你已经可以用print输出你想要的结果了。但是,如果要让用户从电脑输入一些字符怎么办?Python提供了一个input(),可以让用户输入字符串,并存放到一个变量里。比如输入用户的名字,如图2-1-6所示。
在这里插入图片描述

图2-1-6 输入
当你输入name = input()并按下回车后,Python交互式命令行就在等待你的输入了。这时,你可以输入任意字符,然后按回车后完成输入。
输入完成后,不会有任何提示,Python交互式命令行又回到>>>状态了。那我们刚才输入的内容到哪去了?答案是存放到name变量里了。可以直接输入name查看变量内容,如图2-1-7所示。
在这里插入图片描述

图2-1-7 查看变量内容

使用中文“名字”代替英文“name”作为变量名,试一下,如图2-1-8所示。
在这里插入图片描述

图2-1-8 变量名
输入中文变量名‘名字’,显示变量内存储的内容‘米老鼠’,如图2-1-9所示。
在这里插入图片描述

图2-1-9变量内容
什么是变量?请回忆初中数学所学的代数基础知识:
设正方形的边长为a,则正方形的面积为a x a。把边长a看做一个变量,我们就可以根据a的值计算正方形的面积,比如:
若a=2,则面积为a x a = 2 x 2 = 4;
若a=3.5,则面积为a x a = 3.5 x 3.5 = 12.25。
在计算机程序中,变量不仅可以为整数或浮点数,还可以是字符串,因此,name作为一个变量就是一个字符串。

要打印出name变量的内容,除了直接写name然后按回车外,还可以用print语句,如图2-1-10所示。
在这里插入图片描述

图2-1-10 print语句
有了输入和输出,我们就可以新建程序,把上次打印’hello, world’的程序改成有点意义的程序了,图2-1-11所示。
在这里插入图片描述

图2-1-11 输入和输出
按F5运行上面的程序,第一行代码会让用户输入任意字符作为自己的名字,然后存入name变量中;第二行代码会根据用户的名字向用户说hello,比如输入米老鼠,如图2-1-12所示。
在这里插入图片描述

图2-1-12 运行
但是程序运行的时候,没有任何提示信息告诉用户:“嘿,赶紧输入你的名字”,这样显得很不友好。幸好,input可以让你显示一个字符串来提示用户,于是我们把代码改成下面的样子,如图2-1-13所示。
在这里插入图片描述

图2-1-13 提示用户
按F5再次运行这个程序,你会发现,程序一运行,会首先打印出please enter your name:,这样,用户就可以根据提示,输入名字后,得到hello, xxx的输出,如图2-1-14所示。
在这里插入图片描述

图2-1-14
每次运行该程序,根据用户输入的不同,输出结果也会不同。
在命令行下,输入和输出就是这么简单。
小结
任何计算机程序都是为了执行一个特定的任务,有了输入,用户才能告诉计算机程序所需的信息,有了输出,程序运行后才能告诉用户任务的结果。
输入是Input,输出是Output,因此,我们把输入输出统称为Input/Output,或者简写为IO。
input和print是在命令行下面最基本的输入和输出,但是,用户也可以通过其他更高级的图形界面完成输入和输出,比如,在网页上的一个文本框输入自己的名字,点击“确定”后在网页上看到输出信息。

2.1.3 数字

把python当作一个简单的计算器,可以向其录入一些表达式,它会给出返回值。使用运算符 +,-,* 和 /进行计算,括号 (()) 用于分组。如图2-1-15所示
在这里插入图片描述

图2-1-15 简单的计算器
整数(例如,8, 16, 60 )的类型是 int,带有小数部分的数字(例如,15.0, 1.6)的类型是 float。后面我们会看到更多关于数字类型的内容。
除法(/)永远返回一个浮点数。如要使用 floor 除法 并且得到整数结果(丢掉任何小数部分),你可以使用 // 运算符;要计算余数你可以使用 %,如图2-1-16所示。
在这里插入图片描述

图2-1-16 除法运算
通过 Python,还可以使用 ** 运算符计算幂乘方,如图2-1-17所示。
在这里插入图片描述

图2-1-17 计算幂乘方
等号’=’用于给变量赋值。赋值之后,在下一个提示符之前不会有任何结果显示,如图2-1-18所示。
在这里插入图片描述

图2-1-18 变量赋值
变量在使用前必须 “定义”(赋值),否则会出错,如图2-1-19所示。
在这里插入图片描述

图2-1-19 变量未赋值
浮点数有完整的支持;整数和浮点数的混合计算中,整数会被转换为浮点数,如图2-1-20所示。
在这里插入图片描述

图2-1-20 浮点运算
交互模式中,最近一个表达式的值赋给变量 _。这样我们就可以把它当作一个桌面计算器,很方便的用于连续计算,如图2-1-21所示。
在这里插入图片描述

图2-1-21 连续计算
此变量对于用户是只读的。不要尝试给它赋值 —— 你只会创建一个独立的同名局部变量,它屏蔽了系统内置变量的魔术效果。
除了 int 和 float,Python 还支持其它数字类型,例如 Decimal 和 Fraction。Python 还内建支持 复数 ,使用后缀 j 或 J 表示虚数部分(例如,3+5j)。

2.1.4 字符串

相比数值,Python 也提供了可以通过几种不同方式表示的字符串。它们可以用单引号 (‘’) 或双引号 (“”) 标识,注意引号和括号等必需是英文半角符号。\ 可以用来转义引号,如图2-1-22所示。
在这里插入图片描述

图2-1-22 字符串
在交互式解释器中,输出的字符串会用引号引起来。print() 函数生成可读性更好的输出, 它会省去引号并且打印出转义后的特殊字符,如图2-1-23所示。
在这里插入图片描述

图2-1-23 交互输出
如果你前面带有 \ 的字符被当作特殊字符,你可以使用原始字符串,方法是在第一个引号前面加上一个 r,如图2-1-24所示。
在这里插入图片描述

图2-1-24 原始字符串
字符串文本能够分成多行。一种方法是使用三引号:“”“…”“” 或者 ‘’‘…’‘’。行尾换行符会被自动包含到字符串中,但是可以在行尾加上 \ 来避免这个行为。下面的示例: 可以使用反斜杠为行结尾的连续字符串,它表示下一行在逻辑上是本行的后续内容,将生成以下输出(注意,没有开始的第一行),如图2-1-25所示。
在这里插入图片描述

图2-1-25 三引号
字符串可以由 + 操作符连接(粘到一起),可以由 * 表示重复,如图2-1-26所示。
在这里插入图片描述

图2-1-26 字符串连接与重复

相邻的两个字符串文本自动连接在一起,如图2-1-27所示。
在这里插入图片描述

图2-1-27 相邻字符串

它只用于两个字符串文本,不能用于字符串表达式,如图2-1-28所示。
在这里插入图片描述

图2-1-28 字符表达式

如果你想连接多个变量或者连接一个变量和一个字符串文本,使用 +,如图2-1-29所示。
在这里插入图片描述

图2-1-29 连接字符串变量

这个功能在你想切分很长的字符串的时候特别有用,如图2-1-30所示。
在这里插入图片描述

图2-1-30字符串多行输入

字符串也可以被截取(检索)。类似于 C ,字符串的第一个字符索引为 0 。Python没有单独的字符类型;一个字符就是一个简单的长度为1的字符串,如图2-1-31所示。
在这里插入图片描述

图2-1-31 字符截取
索引也可以是负数,这将导致从右边开始计算,如图2-1-32所示。
在这里插入图片描述

图2-1-32 负数索引
请注意 -0 实际上就是 0,所以它不会导致从右边开始计算。
除了索引,还支持 切片。索引用于获得单个字符,切片让你获得一个子字符串,如图2-1-33所示。
在这里插入图片描述

图2-1-33 切片
注意,包含起始的字符,不包含末尾的字符。这使得 s[:i] + s[i:] 永远等于 s,如图2-1-34所示。
在这里插入图片描述

图2-1-34 切片范围
切片的索引有非常有用的默认值;省略的第一个索引默认为零,省略的第二个索引默认为切片的字符串的大小,如图2-1-35所示。
在这里插入图片描述

图2-1-35 默认索引切片
有个办法可以很容易地记住切片的工作方式:切片时的索引是在两个字符 之间 。左边第一个字符的索引为 0,而长度为 n 的字符串其最后一个字符的右界索引为 n。例如:

±–±–±–±–±–±–+
| P | y | t | h | o | n |
±–±–±–±–±–±–+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1

文本中的第一行数字给出字符串中的索引点 0...6。第二行给出相应的负索引。切片是从 i 到 j 两个数值标示的边界之间的所有字符。
对于非负索引,如果上下都在边界内,切片长度就是两个索引之差。例如,word[1:3] 是 2 。

试图使用太大的索引会导致错误,如图2-1-36所示。
在这里插入图片描述

图2-1-36 索引太大
Python 能够优雅地处理那些没有意义的切片索引:一个过大的索引值(即下标值大于字符串实际长度)将被字符串实际长度所代替,当上边界比下边界大时(即切片左值大于右值)就返回空字符,如图2-1-37所示。
在这里插入图片描述

图2-1-37 容错过大的切片索引
Python字符串不可以被更改 — 它们是不可变的 。因此,赋值给字符串索引的位置会导致错误,如图2-1-38所示。
在这里插入图片描述

图2-1-38 字符串不允许更改
如果你需要一个不同的字符串,你应该创建一个新的,如图2-1-39所示。
在这里插入图片描述

图2-1-39 创建新字符串
内置函数 len() 返回字符串长度,如图2-1-40所示。
在这里插入图片描述

图2-1-40 字符串长度

 相关知识

1、Python 支持三种不同的数值类型:
• 整型(Int) - 通常被称为是整型或整数,是正或负整数,不带小数点。Python3 整型是没有限制大小的,可以当作 Long 类型使用,所以 Python3 没有 Python2 的 Long 类型。
• 浮点型(float) - 浮点型由整数部分与小数部分组成,浮点型也可以使用科学计数法表示(2.5e2 = 2.5 x 102 = 250)
• 复数( (complex)) - 复数由实数部分和虚数部分构成,可以用a + bj,或者complex(a,b)表示, 复数的实部a和虚部b都是浮点型。
数值类型实例
在这里插入图片描述
2、Python 数字类型转换
有时候,我们需要对数据内置的类型进行转换,数据类型的转换,你只需要将数据类型作为函数名即可。
• int(x) 将x转换为一个整数。
• float(x) 将x转换到一个浮点数。
• complex(x) 将x转换到一个复数,实数部分为 x,虚数部分为 0。
• complex(x, y) 将 x 和 y 转换到一个复数,实数部分为 x,虚数部分为 y。x 和 y 是数字表达式。
3、Python算术运算符
以下假设变量a为10,变量b为21:
在这里插入图片描述
4、Python比较运算符
以下假设变量a为10,变量b为20:
在这里插入图片描述
5、Python赋值运算符
以下假设变量a为10,变量b为20:
在这里插入图片描述
6、Python位运算符
按位运算符是把数字看作二进制来进行计算的。Python中的按位运算法则如下:
在这里插入图片描述

7、Python逻辑运算符
Python语言支持逻辑运算符,以下假设变量 a 为 10, b为 20:
在这里插入图片描述
8、Python成员运算符
除了以上的一些运算符之外,Python还支持成员运算符,测试实例中包含了一系列的成员,包括字符串,列表或元组。
在这里插入图片描述
9、Python运算符优先级
以下表格列出了从最高到最低优先级的所有运算符:
在这里插入图片描述

10、数学函数
在这里插入图片描述
11、随机数函数
随机数可以用于数学,游戏,安全等领域中,还经常被嵌入到算法中,用以提高算法效率,并提高程序的安全性。
Python包含以下常用随机数函数:
在这里插入图片描述
12、三角函数
Python包括以下三角函数:
在这里插入图片描述
13、数学常量
在这里插入图片描述

 任务评价

请学生按照下表中的要求完成本次评价,并在物理机桌面上以自己的两位学号+姓名的形式命名文件夹,保存所有截图软件,文件保存为jpeg或 png格式。
在这里插入图片描述

 任务拓展

1、输入两个数字,并计算两个数字之差。
2、输入两个数字,并计算两个数的乘积。
3、计算三角形的面积
4、输出一首诗歌。

任务2.2 使用组合数据类型

任务描述
公司接到一个项目需要使用Python进行编程,项目经理布置任务需要我们小组进行编程的准备并写出例子程序。请大家和我一起熟悉python组合数据类型的使用,进行准备并使用Python编程。
任务分析
组合数据类型
 列表
 元组
 集合
 字典
任务实施

2.2.1 列表

1)列表初步
Python 有几个复合数据类型,用于表示其它的值。最通用的是 list (列表) ,它可以写作中括号之间的一列逗号分隔的值。列表的元素不必是同一类型,如图2-2-1所示。
在这里插入图片描述

图2-2-1 列表
就像字符串(以及其它所有内建的 序列 类型)一样,列表可以被索引和切片,如图2-2-2所示。
在这里插入图片描述

图2-2-2 索引和切片
所有的切片操作都会返回一个包含请求的元素的新列表。这意味着下面的切片操作返回列表一个新的(浅)拷贝副本,如图2-2-3所示。
在这里插入图片描述

图2-2-3 切片
列表也支持连接这样的操作,如图2-2-4所示。
在这里插入图片描述

图2-2-4 连接
不像不可变的 字符串,列表是可变的,它允许修改元素,如图2-2-5所示。
在这里插入图片描述

图2-2-5 修改元素
你还可以使用 append() 方法 (后面我们会看到更多关于列表的方法的内容)在列表的末尾添加新的元素,如图2-2-6所示。
在这里插入图片描述

图2-2-6 添加元素

也可以对切片赋值,此操作可以改变列表的尺寸,或清空它,如图2-2-7所示。
在这里插入图片描述

图2-2-7 切片赋值
内置函数 len() 同样适用于列表,如图2-2-8所示。
在这里插入图片描述

图2-2-8 长度
允许嵌套列表(创建一个包含其它列表的列表),如图2-2-9所示。
在这里插入图片描述

图2-2-9 列表嵌套

2)列表的方法

Python 的列表数据类型包含更多的方法。这里是所有的列表对象方法,如下表所示。
在这里插入图片描述

下面这个示例使用Python3.6.1演示了列表的大部分方法,如图2-2-10所示。
在这里插入图片描述
图2-2-10 列表的方法

也许大家会发现像 insert, remove 或者 sort 这些修改列表的方法没有打印返回值–它们返回 None。在 python 中对所有可变的数据类型这是统一的设计原则。

3)把列表当作堆栈使用

列表方法使得列表可以很方便的做为一个堆栈来使用,堆栈作为特定的数据结构,最先进入的元素最后一个被释放(后进先出)。用 append() 方法可以把一个元素添加到堆栈顶。用不指定索引的 pop() 方法可以把一个元素从堆栈顶释放出来,如图2-2-11所示。
在这里插入图片描述

图2-2-11 堆栈

4)把列表当作队列使用

你也可以把列表当做队列使用,队列作为特定的数据结构,最先进入的元素最先释放(先进先出)。不过,列表这样用效率不高。相对来说从列表末尾添加和弹出很快;在头部插入和弹出很慢(因为,为了一个元素,要移动整个列表中的所有元素)。

要实现队列,使用 collections.deque,它为在首尾两端快速插入和删除而设计,如图2-2-12所示。
在这里插入图片描述

图2-2-12 队列

5)列表推导式

列表推导式为从序列中创建列表提供了一个简单的方法。普通的应用程式通过将一些操作应用于序列的每个成员并通过返回的元素创建列表,或者通过满足特定条件的元素创建子序列。

例如, 假设我们创建一个 squares 列表, 可以像下面方式,如图2-2-13所示。
在这里插入图片描述

图2-2-13 创建列表

注意这个 for 循环中的被创建(或被重写)的名为 x 的变量在循环完毕后依然存在。
使用如下方法,我们可以计算squares的值而不会产生任何的副作用,如图2-2-14所示。
在这里插入图片描述

图2-2-14 list
或者,等价于,如图2-2-15所示。
在这里插入图片描述

图2-2-15 Lambda表达式
上面这个方法更加简明且易读.

列表推导式由包含一个表达式的括号组成,表达式后面跟随一个 for 子句,之后可以有零或多个 for 或 if 子句。结果是一个列表,由表达式依据其后面的 for 和 if 子句上下文计算而来的结果构成。

例如,如下的列表推导式结合两个列表的元素,如果元素之间不相等的话,如图2-2-16所示。
在这里插入图片描述

图2-2-16 列表推导式
等同于,如图2-2-17所示。
在这里插入图片描述

图2-2-17 另一种实现
值得注意的是在上面两个方法中的 for 和 if 语句的顺序。

如果想要得到一个元组(例如,上面例子中的 (x, y)),必须要加上括号,如图2-2-18所示。

在这里插入图片描述

图2-2-18 列表与元组

列表推导式可使用复杂的表达式和嵌套函数,如图2-2-19所示。
在这里插入图片描述

图2-2-19 列表推导式

6)嵌套的列表推导式

列表解析中的第一个表达式可以是任何表达式,包括列表解析。

考虑下面由三个长度为 4 的列表组成的 3x4 矩阵,如图2-2-20所示。
在这里插入图片描述

图2-2-20矩阵

现在,如果你想交换行和列,可以用嵌套的列表推导式,如图2-2-21所示。
在这里插入图片描述

图2-2-21 嵌套的列表推导式

像前面看到的,嵌套的列表推导式是对 for 后面的内容进行求值,所以上例就等价于,如图2-2-22所示。
在这里插入图片描述

图2-2-22 等价程序
反过来说,如下也是一样的,如图2-2-23所示。
在这里插入图片描述

图2-2-23 另一种实现

在实际中,你应该更喜欢使用内置函数组成复杂流程语句。对此种情况 zip() 函数将会做的更好,如图2-2-24所示。
在这里插入图片描述

图2-2-24 zip

更多关于本行中使用的星号的说明,参考 参数列表的分拆。

7)del 语句

有个方法可以从列表中按给定的索引而不是值来删除一个子项: del 语句。它不同于有返回值的 pop() 方法。语句 del 还可以从列表中删除切片或清空整个列表(我们以前介绍过一个方法是将空列表赋值给列表的切片),如图2-2-25所示。
在这里插入图片描述

图2-2-25 del

del 也可以删除整个变量,此后再引用命名 a 会引发错误(直到另一个值赋给它为止)。我们在后面的内容中可以看到 del 的其它用法,如图2-2-26所示。
在这里插入图片描述

图2-2-26 删除后引用报错

2.2.2 元组

我们知道列表和字符串有很多通用的属性,例如索引和切割操作。它们是 序列 类型(参见 Sequence Types — list, tuple, range )中的两种。因为 Python 是一个在不停进化的语言,也可能会加入其它的序列类型,这里介绍另一种标准序列类型: 元组 。

一个元组由数个逗号分隔的值组成,如图2-2-27所示。
在这里插入图片描述

图2-2-27 元组

如你所见,元组在输出时总是有括号的,以便于正确表达嵌套结构。在输入时可以有或没有括号,不过经常括号都是必须的(如果元组是一个更大的表达式的一部分)。不能给元组的一个独立的元素赋值(尽管你可以通过联接和切割来模拟)。还可以创建包含可变对象的元组,例如列表。

虽然元组和列表很类似,它们经常被用来在不同的情况和不同的用途。元组有很多用途。例如 (x, y) 坐标对,数据库中的员工记录等等。元组就像字符串, 不可变的。通常包含不同种类的元素并通过分拆(参阅本节后面的内容) 或索引访问(如果是 namedtuples,甚至可以通过属性)。列表是可变的 ,它们的元素通常是相同类型的并通过迭代访问。

一个特殊的问题是构造包含零个或一个元素的元组:为了适应这种情况,语法上有一些额外的改变。一对空的括号可以创建空元组;要创建一个单元素元组可以在值后面跟一个逗号(在括号中放入一个单值不够明确)。丑陋,但是有效,如图2-2-28所示。
在这里插入图片描述

图2-2-28 单元素元组

语句 t = 12345, 54321, ‘hello!’ 是 元组封装 (tuple packing)的一个例子:值 12345 , 54321 和 ‘hello!’ 被封装进元组。其逆操作可能是这样,如图2-2-29所示。
在这里插入图片描述

图2-2-29 序列拆封
这个调用等号右边可以是任何线性序列,称之为序列拆封非常恰当。序列拆封要求左侧的变量数目与序列的元素个数相同。要注意的是可变参数(multiple assignment )其实只是元组封装和序列拆封的一个结合。

2.2.3 集合

Python 还包含了一个数据类型 —— set (集合)。集合是一个无序不重复元素的集。基本功能包括关系测试和消除重复元素。集合对象还支持 union(联合),intersection(交),difference(差)和 sysmmetric difference(对称差集)等数学运算。

大括号或 set() 函数可以用来创建集合。注意:想要创建空集合,你必须使用 set() 而不是 {}。后者用于创建空字典,我们在下一节中介绍的一种数据结构。

以下是一个简单的演示,如图2-2-30所示。
在这里插入图片描述

图2-2-30 创建集合
集合,如图2-2-31所示。
在这里插入图片描述

图2-2-31 set创建集合

类似列表推导式,这里有一种集合推导式语法,如图2-2-32所示。
在这里插入图片描述

图2-2-32 集合推导式

2.2.4 字典

另一个非常有用的 Python 内建数据类型是 字典 (参见 Mapping Types — dict )。字典在某些语言中可能称为 联合内存 ( associative memories )或 联合数组 ( associative arrays )。序列是以连续的整数为索引,与此不同的是,字典以 关键字 为索引,关键字可以是任意不可变类型,通常用字符串或数值。如果元组中只包含字符串和数字,它可以做为关键字,如果它直接或间接的包含了可变对象,就不能当做关键字。不能用列表做关键字,因为列表可以用索引、切割或者 append() 和 extend() 等方法改变。
理解字典的最佳方式是把它看做无序的键: 值对 (key:value 对)集合,键必须是互不相同的(在同一个字典之内)。一对大括号创建一个空的字典: {} 。初始化列表时,在大括号内放置一组逗号分隔的键:值对,这也是字典输出的方式。
字典的主要操作是依据键来存储和析取值。也可以用 del 来删除键:值对(key:value)。如果你用一个已经存在的关键字存储值,以前为该关键字分配的值就会被遗忘。试图从一个不存在的键中取值会导致错误。
对一个字典执行 list(d.keys()) 将返回一个字典中所有关键字组成的无序列表(如果你想要排序,只需使用 sorted(d.keys()) )。[2] 使用 in 关键字(指Python语法)可以检查字典中是否存在某个关键字(指字典)。
这里是使用字典的一个小示例,如图2-2-33所示。
在这里插入图片描述

图2-2-33 字典

dict() 构造函数可以直接从 key-value 对中创建字典,如图2-2-34所示。
在这里插入图片描述

图2-2-34 构造函数

此外,字典推导式可以从任意的键值表达式中创建字典,如图2-2-35所示。
在这里插入图片描述

图2-2-35 字典推导式

如果关键字都是简单的字符串,有时通过关键字参数指定 key-value 对更为方便,如图2-2-36所示。
在这里插入图片描述

图2-2-36 关键字参数

 相关知识

1、Python3 中有六个标准的数据类型
• Number(数字)
• String(字符串)
• List(列表)
• Tuple(元组)
• Sets(集合)
• Dictionary(字典)
2、Python数据类型转换
有时候,我们需要对数据内置的类型进行转换,数据类型的转换,你只需要将数据类型作为函数名即可。
以下几个内置的函数可以执行数据类型之间的转换。这些函数返回一个新的对象,表示转换的值。
在这里插入图片描述
3、Python转义字符
在需要在字符中使用特殊字符时,python用反斜杠()转义字符。如下表:
在这里插入图片描述

4、Python字符串运算符
下表实例变量a值为字符串 “Hello”,b变量值为 “Python”:
在这里插入图片描述

5、Python字符串格式化
Python 支持格式化字符串的输出 。尽管这样可能会用到非常复杂的表达式,但最基本的用法是将一个值插入到一个有字符串格式符 %s 的字符串中。
在 Python 中,字符串格式化使用与 C 中 sprintf 函数一样的语法。
6、实例(Python 3.0+)
#!/usr/bin/python3 print (“我叫 %s 今年 %d 岁!” % (‘小明’, 10))
以上实例输出结果:
我叫 小明 今年 10 岁!
python字符串格式化符号:
在这里插入图片描述

7、格式化操作符辅助指令
在这里插入图片描述

Python2.6 开始,新增了一种格式化字符串的函数 str.format(),它增强了字符串格式化的功能。

8、Python 的字符串内建函数
Python 的字符串常用内建函数如下:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

 任务评价

请学生按照下表中的要求完成本次评价,并在物理机桌面上以自己的两位学号+姓名的形式命名文件夹,保存所有截图软件,文件保存为jpeg或 png格式。
在这里插入图片描述

 任务拓展

1、 使用列表,输入保存并输出演员表。
2、 使用列表,生成两个演员表,并将两个演员表合成一个。
3、 使用词典,输入保存并输出通讯录。
4、 使用列表推导式,计算1-100之间每一个整数的平方。

任务2.3 使用控制结构

任务描述
公司接到一个项目需要使用Python进行编程,项目经理布置任务需要我们小组进行编程的准备并写出一个例子程序。请大家和我一起熟悉python控制结构的使用,进行准备并使用Python编程。
任务分析
控制结构
If
while
for
try
任务实施

2.3.1 if 语句

也许最有名的是 if 语句,注意每个级别之间留四个英文字符的缩进,如图2-3-1所示。
在这里插入图片描述

图2-3-1 if语句

可能会有零到多个 elif 部分,else 是可选的。关键字 ‘elif‘ 是 ’else if’ 的缩写,这个可以有效地避免过深的缩进。if … elif … elif … 序列用于替代其它语言中的 switch 或 case 语句。

2.3.2 while 循环

当然,我们可以使用 Python 完成比二加二更复杂的任务。例如,我们可以写一个生成 菲波那契 子序列的程序,如图2-3-2所示。

在这里插入图片描述

图2-3-2 while循环

这个例子介绍了几个新功能。
第一行包括了一个 多重赋值:变量 a 和 b 同时获得了新的值 0 和 1 最后一行又使用了一次。
在这个演示中,变量赋值前,右边首先完成计算。右边的表达式从左到右计算。
条件(这里是 b < 10 )为 true 时, while 循环执行。在 Python 中,类似于 C,任何非零整数都是 true;0 是 false。条件也可以是字符串或列表,实际上可以是任何序列;
所有长度不为零的是 true,空序列是 false。示例中的测试是一个简单的比较。标准比较操作符与 C 相同: < , > , == , <=, >= 和 !=。
循环 体 是 缩进 的:缩进是 Python 组织语句的方法。Python (还)不提供集成的行编辑功能,所以你要为每一个缩进行输入 TAB 或空格。
实践中建议你找个文本编辑来录入复杂的 Python 程序,大多数文本编辑器提供自动缩进。交互式录入复合语句时,必须在最后输入一个空行来标识结束(因为解释器没办法猜测你输入的哪一行是最后一行),需要 注意的是同一个语句块中的每一行必须缩进同样数量的空白。
关键字 print() 语句输出给定表达式的值。它控制多个表达式和字符串输出为你想要字符串(就像我们在前面计算器的例子中那样)。
字符串打印时不用引号包围,每两个子项之间插入空间,所以你可以把格式弄得很漂亮,如图2-3-3所示。
在这里插入图片描述

图2-3-3 漂亮的格式
用一个逗号结尾就可以禁止输出换行,如图2-3-4所示。
在这里插入图片描述

图2-3-4 禁止输出换行

2.3.3 for循环

1)for

Python 中的 for 语句和 C 或 Pascal 中的略有不同。通常的循环可能会依据一个等差数值步进过程(如 Pascal),或由用户来定义迭代步骤和中止条件(如 C ),Python 的 for 语句依据任意序列(链表或字符串)中的子项,按它们在序列中的顺序来进行迭代,如图2-3-5所示。
在这里插入图片描述

图2-3-5 for循环

在迭代过程中修改迭代序列不安全(只有在使用链表这样的可变序列时才会有这样的情况)。如果你想要修改你迭代的序列(例如,复制选择项),你可以迭代它的复本。使用切割标识就可以很方便的做到这一点,如图2-3-6所示。
在这里插入图片描述

图2-3-6 迭代

2)range() 函数

如果你需要一个数值序列,内置函数 range() 会很方便,它生成一个等差级数链表,如图2-3-7所示。
在这里插入图片描述

图2-3-7 数值序列

range(10) 生成了一个包含 10 个值的链表,它用链表的索引值填充了这个长度为 10 的列表,所生成的链表中不包括范围中的结束值。也可以让 range() 操作从另一个数值开始,或者可以指定一个不同的步进值(甚至是负数,有时这也被称为 “步长”) ,如图2-3-8所示。
在这里插入图片描述

图2-3-8 链表

需要迭代链表索引的话,结合使用 range() 和 len(),如图2-3-9所示。
在这里插入图片描述

图2-3-9 迭代链表
不过,这种场合可以方便的使用 enumerate(),请参见 循环技巧。

如果你只是打印一个序列的话会发生奇怪的事情,如图2-3-10所示。
在这里插入图片描述

图2-3-10 打印一个序列

在不同方面 range() 函数返回的对象表现为它是一个列表,但事实上它并不是。当你迭代它时,它是一个能够像期望的序列返回连续项的对象;但为了节省空间,它并不真正构造列表。

我们称此类对象是 可迭代的,即适合作为那些期望从某些东西中获得连续项直到结束的函数或结构的一个目标(参数)。我们已经见过的 for 语句就是这样一个迭代器。list() 函数是另外一个( 迭代器 ),它从可迭代(对象)中创建列表,如图2-3-11所示。
在这里插入图片描述

图2-3-11 创建列表

稍后我们会看到更多返回可迭代(对象)和以可迭代(对象)作为参数的函数。

3)break 和 continue 语句, 以及循环中的 else 子句

break 语句和 C 中的类似,用于跳出最近的一级 for 或 while 循环。

循环可以有一个 else 子句;它在循环迭代完整个列表(对于 for )或执行条件为 false (对于 while )时执行,但循环被 break 中止的情况下不会执行。以下搜索素数的示例程序演示了这个子句,如图2-3-12所示。
在这里插入图片描述

图2-3-12 子句

(Yes, 这是正确的代码。看仔细:else 语句是属于 for 循环之中, 不是 if 语句。)

与循环一起使用时,else 子句与 try 语句的 else 子句比与 if 语句的具有更多的共同点:try 语句的 else 子句在未出现异常时运行,循环的 else 子句在未出现 break 时运行。更多关于 try 语句和异常的内容,请参见 异常处理。

continue 语句是从 C 中借鉴来的,它表示循环继续执行下一次迭代,如图2-3-13所示。
在这里插入图片描述

图2-3-13 继续执行

4)pass 语句

pass 语句什么也不做。它用于那些语法上必须要有什么语句,但程序什么也不做的场合,如图2-3-14所示。
在这里插入图片描述

图2-3-14 什么也不做

while True:
… pass # Busy-wait for keyboard interrupt (Ctrl+C)

这通常用于创建最小结构的类,如图2-3-15所示。
在这里插入图片描述

图2-3-15 最小结构的类

另一方面,pass 可以在创建新代码时用来做函数或控制体的占位符。可以让你在更抽象的级别上思考。pass 可以默默的被忽视,如图2-3-16所示。
在这里插入图片描述

图2-3-16 占位符
5)循环技巧

在字典中循环时,关键字和对应的值可以使用 items() 方法同时解读出来,如图2-3-17所示。
在这里插入图片描述

图2-3-17 字典中循环

在序列中循环时,索引位置和对应值可以使用 enumerate() 函数同时得到,如图2-3-18所示。
在这里插入图片描述

图2-3-18 序列中循环

同时循环两个或更多的序列,可以使用 zip() 整体打包,如图2-3-19所示。
在这里插入图片描述

图2-3-19同时循环多个序列

需要逆向循环序列的话,先正向定位序列,然后调用 reversed() 函数,如图2-3-20所示。
在这里插入图片描述

图2-3-20 逆向循环序列

要按排序后的顺序循环序列的话,使用 sorted() 函数,它不改动原序列,而是生成一个新的已排序的序列,如图2-3-21所示。
在这里插入图片描述

图2-3-21 顺序循环序列

若要在循环内部修改正在遍历的序列(例如复制某些元素),建议您首先制作副本。在序列上循环不会隐式地创建副本。切片表示法使这尤其方便,如图2-3-22所示。
在这里插入图片描述

图2-3-22 循环内部修改遍历的序列

2.3.4 try 异常处理

1)错误和异常
作为Python初学者,在刚学习Python编程时,经常会看到一些报错信息,在前面我们没有提及,这里我们专门进行学习。
Python有两种错误很容易辨认:语法错误和异常。
2)语法错误
Python 的语法错误或者称之为解析错,是初学者经常碰到的,如图2-3-23所示。
在这里插入图片描述

图2-3-23 语法错误
这个例子中,函数 print() 被检查到有错误,是它前面缺少了一个冒号(:)。
语法分析器指出了出错的一行,并且在最先找到的错误的位置标记了一个小小的箭头。
3)异常
即便Python程序的语法是正确的,在运行它的时候,也有可能发生错误。运行期检测到的错误被称为异常。
大多数的异常都不会被程序处理,都以错误信息的形式展现在这里,如图2-3-24所示。
在这里插入图片描述

图2-3-24 错误信息
异常以不同的类型出现,这些类型都作为信息的一部分打印出来: 例子中的类型有 ZeroDivisionError,NameError 和 TypeError。
错误信息的前面部分显示了异常发生的上下文,并以调用栈的形式显示具体信息。
4)异常处理
以下例子中,让用户输入一个合法的整数,但是允许用户中断这个程序(使用 Control-C 或者操作系统提供的方法)。用户中断的信息会引发一个 KeyboardInterrupt 异常,如图2-3-25所示。
在这里插入图片描述

图2-3-25 异常处理
try语句按照如下方式工作;
• 首先,执行try子句(在关键字try和关键字except之间的语句)
• 如果没有异常发生,忽略except子句,try子句执行后结束。
• 如果在执行try子句的过程中发生了异常,那么try子句余下的部分将被忽略。如果异常的类型和 except 之后的名称相符,那么对应的except子句将被执行。最后执行 try 语句之后的代码。
• 如果一个异常没有与任何的except匹配,那么这个异常将会传递给上层的try中。
一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。最多只有一个分支会被执行。
处理程序将只针对对应的try子句中的异常进行处理,而不是其他的 try 的处理程序中的异常。
一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组,例如:

    except (RuntimeError, TypeError, NameError):
        pass

最后一个except子句可以忽略异常的名称,它将被当作通配符使用。你可以使用这种方法打印一个错误信息,然后再次把异常抛出,如图2-3-26所示。
在这里插入图片描述

图2-3-26 excep
try except 语句还有一个可选的else子句,如果使用这个子句,那么必须放在所有的except子句之后。这个子句将在try子句没有发生任何异常的时候执行,如图2-3-27所示。
在这里插入图片描述

图2-3-27 else
使用 else 子句比把所有的语句都放在 try 子句里面要好,这样可以避免一些意想不到的、而except又没有捕获的异常。
异常处理并不仅仅处理那些直接发生在try子句中的异常,而且还能处理子句中调用的函数(甚至间接调用的函数)里抛出的异常,如图2-3-28所示。
在这里插入图片描述

图2-3-28 异常
5)抛出异常
Python 使用 raise 语句抛出一个指定的异常,如图2-3-29所示。
在这里插入图片描述

图2-3-29 抛出异常
raise 唯一的一个参数指定了要被抛出的异常。它必须是一个异常的实例或者是异常的类(也就是 Exception 的子类)。
如果你只想知道这是否抛出了一个异常,并不想去处理它,那么一个简单的 raise 语句就可以再次把它抛出图2-3-30。
在这里插入图片描述

图2-3-30异常再次抛出
6)用户自定义异常
你可以通过创建一个新的exception类来拥有自己的异常。异常应该继承自 Exception 类,或者直接继承,或者间接继承,如图2-3-31所示。
在这里插入图片描述

图2-3-31 自定义异常
在这个例子中,类 Exception 默认的 init() 被覆盖。
<p异常的类可以像其他的类一样做任何事情,但是通常都会比较简单,只提供一些错误相关的属性,并且允许处理异常的代码方便的获取这些信息。< p=“”>
当创建一个模块有可能抛出多种不同的异常时,一种通常的做法是为这个包建立一个基础异常类,然后基于这个基础类为不同的错误情况创建不同的子类,如图2-3-32所示。
在这里插入图片描述

图2-3-32 基础异常类
大多数的异常的名字都以"Error"结尾,就跟标准的异常命名一样。

7)定义清理行为
try 语句还有另外一个可选的子句,它定义了无论在任何情况下都会执行的清理行为,如图2-3-33所示。
在这里插入图片描述

图2-3-33 finally
以上例子不管 try 子句里面有没有发生异常,finally 子句都会执行。
如果一个异常在 try 子句里(或者在 except 和 else 子句里)被抛出,而又没有任何的 except 把它截住,那么这个异常会在 finally 子句执行后再次被抛出。
下面是一个更加复杂的例子(在同一个 try 语句里包含 except 和 finally 子句),如图2-3-34所示。
在这里插入图片描述

图2-3-34 except和 finally
8)预定义的清理行为
一些对象定义了标准的清理行为,无论系统是否成功的使用了它,一旦不需要它了,那么这个标准的清理行为就会执行。
这面这个例子展示了尝试打开一个文件,然后把内容打印到屏幕上,如图2-3-35所示。
在这里插入图片描述

图2-3-35 打印文件内容到屏幕
以上这段代码的问题是,当执行完毕后,文件会保持打开状态,并没有被关闭。
关键词 with 语句就可以保证诸如文件之类的对象在使用完之后一定会正确的执行他的清理方法,如图2-3-36所示。
在这里插入图片描述

图2-3-36 with
以上这段代码执行完毕后,就算在处理过程中出问题了,文件 f 总是会关闭。 异常的类可以像其他的类一样做任何事情,但是通常都会比较简单,只提供一些错误相关的属性,并且允许处理异常的代码方便的获取这些信息。

 相关知识

1、深入条件控制

while 和 if 语句中使用的条件不仅可以使用比较,而且可以包含任意的操作。

比较操作符 in 和 not in 审核值是否在一个区间之内。操作符 is 和 is not 比较两个对象是否相同;这只和诸如列表这样的可变对象有关。所有的比较操作符具有相同的优先级,低于所有的数值操作。

比较操作可以传递。例如 a < b == c 审核是否 a 小于 b 并且 b 等于 c。

比较操作可以通过逻辑操作符 and 和 or 组合,比较的结果可以用 not 来取反义。这些操作符的优先级又低于比较操作符,在它们之中,not 具有最高的优先级, or 优先级最低,所以 A and not B or C 等于 (A and (notB)) or C。当然,括号也可以用于比较表达式。

逻辑操作符 and 和 or 也称作短路操作符:它们的参数从左向右解析,一旦结果可以确定就停止。例如,如果 A 和 C 为真而 B 为假, A and B and C 不会解析 C。作用于一个普通的非逻辑值时,短路操作符的返回值通常是最后一个变量。

可以把比较或其它逻辑表达式的返回值赋给一个变量,如图2-3-23所示。
在这里插入图片描述

图2-3-23 逻辑表达式的返回值

需要注意的是 Python 与 C 不同,在表达式内部不能赋值。C 程序员经常对此抱怨,不过它避免了一类在 C 程序中司空见惯的错误:想要在解析式中使 == 时误用了 = 操作符。

2、比较序列和其它类型

序列对象可以与相同类型的其它对象比较。比较操作按 字典序 进行:首先比较前两个元素,如果不同,就决定了比较的结果;如果相同,就比较后两个元素,依此类推,直到所有序列都完成比较。如果两个元素本身就是同样类 型的序列,就递归字典序比较。如果两个序列的所有子项都相等,就认为序列相等。如果一个序列是另一个序列的初始子序列,较短的一个序列就小于另一个。字符 串的字典序按照单字符的 ASCII 顺序。下面是同类型序列之间比较的一些例子,如图2-3-24所示。
在这里插入图片描述

图2-3-24 同类型序列之间比较

需要注意的是如果通过 < 或者 > 比较的对象只要具有合适的比较方法就是合法的。比如,混合数值类型是通过它们的数值进行比较的,所以 0 是等于 0.0 。否则解释器将会触发一个 TypeError 异常,而不是提供一个随意的结果。

以下为if中常用的操作运算符:
在这里插入图片描述

 任务评价

请学生按照下表中的要求完成本次评价,并在物理机桌面上以自己的两位学号+姓名的形式命名文件夹,保存所有截图软件,文件保存为jpeg或 png格式。
在这里插入图片描述

 任务拓展

1、 通过使用 if…elif…else 语句判断数字是正数、负数或零。
2、 一个大于1的自然数,除了1和它本身外,不能被其他自然数(质数)整除(2, 3, 5, 7等),换句话说就是该数除了1和它本身以外不再有其他的因数。请找出100以内的质数。
3、 显示输出九九乘法表
4、 斐波那契数列,指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13,特别指出:第0项是0,第1项是第一个1。从第三项开始,每一项都等于前两项之和。请显示输出一百以内的斐波那契数列。

任务2.4 使用函数

任务描述
公司接到一个项目需要使用Python进行编程,项目经理布置任务需要我们小组进行编程的准备并写出一个例子程序。请大家和我一起熟悉python函数的使用,进行准备并使用Python编程。
任务分析
python函数的使用包括以下几个方面
 函数的定义
 函数参数的传递
 函数的Lambda形式
 文档字符串
 函数的注解
任务实施

2.4.1 函数

我们可以创建一个用来生成指定边界的斐波那契数列的函数,如图2-4-1所示。
在这里插入图片描述

图2-4-1 斐波那契数列函数

关键字 def 引入了一个函数定义。在其后必须跟有函数名和包括形式参数的圆括号。函数体语句从下一行开始,必须是缩进的。

函数体的第一行语句可以是可选的包含在三引号内的字符串文本,这个字符串是函数的文档字符串,或者称为 docstring,可以生成在线文档或者可打印文档,用来查看函数的功能说明。有些工具通过 docstrings 自动生成在线的或可打印的文档,或者让用户通过代码交互浏览;在你的代码中包含 docstrings 是一个好的实践,让它成为习惯吧。

函数 调用 会为函数局部变量生成一个新的符号表。确切的说,所有函数中的变量赋值都是将值存储在局部符号表。变量引用首先在局部符号表中查找,然后是包含函数的局部符号表,然后是全局符号表,最后是内置名字表。因此,全局变量不能在函数中直接赋值(除非用 global 语句命名),尽管他们可以被引用。

函数引用的实际参数在函数调用时引入局部符号表,因此,实参总是 传值调用 (这里的 值 总是一个对象 引用 ,而不是该对象的值)。[1] 一个函数被另一个函数调用时,一个新的局部符号表在调用过程中被创建。

一个函数定义会在当前符号表内引入函数名。函数名指代的值(即函数体)有一个被 Python 解释器认定为 用户自定义函数的类型。这个值可以赋予其他的名字(即变量名),然后它也可以被当做函数使用。这可以作为通用的重命名机制,如图2-4-2所示。
在这里插入图片描述

图2-4-2 函数重命名

如果你使用过其他语言,你可能会反对说:fib 不是一个函数,而是一个方法,因为它并不返回任何值。事实上,没有 return 语句的函数确实会返回一个值,虽然是一个相当令人厌烦的值(指 None )。这个值被称为 None (这是一个内建名称)。如果 None 值是唯一被书写的值,那么在写的时候通常会被解释器忽略(即不输出任何内容)。如果你确实想看到这个值的输出内容,请使用 print() 函数,如图2-4-3所示。
在这里插入图片描述

图2-4-3 返回值

定义一个返回斐波那契数列数字列表的函数,而不是打印它,是很简单的,如图2-4-4所示。
在这里插入图片描述

图2-4-4 返回斐波那契数列数字列表的函数

和以前一样,这个例子演示了一些新的 Python 功能:

return 语句从函数中返回一个值,不带表达式的 return 返回 None。

过程结束后也会返回 None。

语句 result.append(b) 称为链表对象 result 的一个 方法。方法是一个“属于”某个对象的函数,它被命名为 obj.methodename,这里的 obj 是某个对象(可能是一个表达式), methodename 是某个在该对象类型定义中的方法的命名。

不同的类型定义不同的方法。不同类型可能有同样名字的方法,但不会混淆。(当你定义自己的对象类型和方法时,可能会出现这种情况,class 的定义方法详见 类 )。示例中演示的 append() 方法由链表对象定义,它向链表中加入一个新元素。在示例中它等同于 result = result + [a],不过效率更高。

2.4.2 函数参数的传递

在 Python 中,你也可以定义包含若干参数的函数。这里有三种可用的形式,也可以混合使用。

1)默认参数值

最常用的一种形式是为一个或多个参数指定默认值。这会创建一个可以使用比定义时允许的参数更少的参数调用的函数,如图2-4-5所示。
在这里插入图片描述

图2-4-5默认值参数

这个函数可以通过几种不同的方式调用:

只给出必要的参数:
ask_ok('Do you really want to quit?')

给出一个可选的参数:
ask_ok('OK to overwrite the file?', 2)

或者给出所有的参数:
ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')

这个例子还介绍了 in 关键字。它测定序列中是否包含某个确定的值。

默认值在函数定义作用域被解析,如图2-4-6所示。
在这里插入图片描述

图2-4-6默认值

重要警告: 默认值只被赋值一次。这使得当默认值是可变对象时会有所不同,比如列表、字典或者大多数类的实例。例如,下面的函数在后续调用过程中会累积(前面)传给它的参数,如图2-4-7所示。
在这里插入图片描述

图2-4-7 参数累积

如果你不想让默认值在后续调用中累积,你可以像下面一样定义函数,如图2-4-8所示。
在这里插入图片描述

图2-4-8 避免参数累积

2)关键字参数

函数可以通过 关键字参数的形式来调用,形如 keyword = value。例如,以下的函数,如图2-4-9所示。
在这里插入图片描述

图2-4-9 关键字参数

接受一个必选参数 (voltage) 以及三个可选参数 (state, action, 和 type)。可以用以下的任一方法调用:

parrot(1000) # 1 positional argument
parrot(voltage=1000) # 1 keyword argument
parrot(voltage=1000000, action=‘VOOOOOM’) # 2 keyword arguments
parrot(action=‘VOOOOOM’, voltage=1000000) # 2 keyword arguments
parrot(‘a million’, ‘bereft of life’, ‘jump’) # 3 positional arguments
parrot(‘a thousand’, state=‘pushing up the daisies’) # 1 positional, 1 keyword

不过以下几种调用是无效的:

parrot() # required argument missing
parrot(voltage=5.0, ‘dead’) # non-keyword argument after a keyword argument
parrot(110, voltage=220) # duplicate value for the same argument
parrot(actor=‘John Cleese’) # unknown keyword argument

在函数调用中,关键字的参数必须跟随在位置参数的后面。传递的所有关键字参数必须与函数接受的某个参数相匹配 (例如 actor 不是 parrot 函数的有效参数),它们的顺序并不重要。这也包括非可选参数(例如 parrot(voltage=1000) 也是有效的)。任何参数都不可以多次赋值。下面的示例由于这种限制将失败,如图2-4-10所示。
在这里插入图片描述

图2-4-10 参数不可以多次赋值

引入一个形如 **name 的参数时,它接收一个字典(参见 Mapping Types — dict ),该字典包含了所有未出现在形式参数列表中的关键字参数。这里可能还会组合使用一个形如 *name (下一小节详细介绍) 的形式参数,它接收一个元组(下一节中会详细介绍),包含了所有没有出现在形式参数列表中的参数值( *name 必须在 **name 之前出现)。 例如,我们这样定义一个函数,如图2-4-11所示。
在这里插入图片描述

图2-4-11 接收一个元组

它可以像这样调用,如图2-4-12所示。
在这里插入图片描述

图2-4-12 调用

注意在打印关键字参数之前,通过对关键字字典 keys() 方法的结果进行排序,生成了关键字参数名的列表;如果不这样做,打印出来的参数的顺序是未定义的。
3)可变参数列表

最后,一个最不常用的选择是可以让函数调用可变个数的参数。这些参数被包装进一个元组(参见 元组和序列 )。在这些可变个数的参数之前,可以有零到多个普通的参数,如图2-4-13所示。
在这里插入图片描述

图2-4-13 可变参数列表

通常,这些可变参数是参数列表中的最后一个,因为它们将把所有的剩余输入参数传递给函数。任何出现在 *args 后的参数是关键字参数,这意味着,他们只能被用作关键字,而不是位置参数,如图2-4-14所示。
在这里插入图片描述

图2-4-14 最后一个

4)参数列表的分拆

另有一种相反的情况: 当你要传递的参数已经是一个列表,但要调用的函数却接受分开一个个的参数值。这时候你要把已有的列表拆开来。例如内建函数 range() 需要要独立的 start,stop 参数。你可以在调用函数时加一个 * 操作符来自动把参数列表拆开,如图2-4-15所示。
在这里插入图片描述

图2-4-15 参数列表分拆

以同样的方式,可以使用 ** 操作符分拆关键字参数为字典,如图2-4-16所示。
在这里插入图片描述

图2-4-16 分拆关键字参数为字典

2.4.3 函数的Lambda 形式

出于实际需要,有几种通常在函数式编程语言例如 Lisp 中出现的功能加入到了 Python。通过 lambda 关键字,可以创建短小的匿名函数。这里有一个函数返回它的两个参数的和: lambda a, b: a+b。 Lambda 形式可以用于任何需要的函数对象。出于语法限制,它们只能有一个单独的表达式。语义上讲,它们只是普通函数定义中的一个语法技巧。类似于嵌套函数定义,lambda 形式可以从外部作用域引用变量,如图2-4-17所示。
在这里插入图片描述

图2-4-17 lambda 形式

上面的示例使用 lambda 表达式返回一个函数。另一个用途是将一个小函数作为参数传递,如图2-4-18所示。
在这里插入图片描述

图2-4-18 参数传递

2.4.4 文档字符串

这里介绍的文档字符串的概念和格式。
第一行应该是关于对象用途的简介。简短起见,不用明确的陈述对象名或类型,因为它们可以从别的途径了解到(除非这个名字碰巧就是描述这个函数操作的动词)。这一行应该以大写字母开头,以句号结尾。
如果文档字符串有多行,第二行应该空出来,与接下来的详细描述明确分隔。接下来的文档应该有一或多段描述对象的调用约定、边界效应等。
Python 的解释器不会从多行的文档字符串中去除缩进,所以必要的时候应当自己清除缩进。这符合通常的习惯。第一行之后的第一个非空行决定了整个文档的缩进格式。(我们不用第一行是因为它通常紧靠着起始的引号,缩进格式显示的不清楚。)留白“相当于”是字符串的起始缩进。每一行都不应该有缩进,如果有缩进的话,所有的留白都应该清除掉。留白的长度应当等于扩展制表符的宽度(通常是8个空格)。
以下是一个多行文档字符串的示例,如图2-4-19所示。
在这里插入图片描述

图2-4-19 多行文档字符串

2.4.5 函数注解

函数注解 是关于用户自定义的函数的完全可选的、随意的元数据信息。无论 Python 本身或者标准库中都没有使用函数注解;本节只是描述了语法。第三方的项目是自由地为文档,类型检查,以及其它用途选择函数注解。
注解是以字典形式存储在函数的 annotations 属性中,对函数的其它部分没有任何影响。参数注解(Parameter annotations)是定义在参数名称的冒号后面,紧随着一个用来表示注解的值得表达式。返回注释(Return annotations)是定义在一个 -> 后面,紧随着一个表达式,在冒号与 -> 之间。下面的示例包含一个位置参数,一个关键字参数,和没有意义的返回值注释,如图2-4-20所示。
在这里插入图片描述

图2-4-20 返回值注释

 相关知识

编码风格
此时你已经可以写一些更长更复杂的 Python 程序,是时候讨论一下 编码风格 了。大多数语言可以写(或者更明白的说, 格式化 )作几种不同的风格。有些比其它的更好读。让你的代码对别人更易读是个好想法,养成良好的编码风格对此很有帮助。
对于 Python,PEP 8 引入了大多数项目遵循的风格指导。它给出了一个高度可读,视觉友好的编码风格。每个 Python 开发者都应该读一下,大多数要点都会对你有帮助:
 使用 4 空格缩进,而非 TAB
 在小缩进(可以嵌套更深)和大缩进(更易读)之间,4空格是一个很好的折中。TAB 引发了一些混乱,最好弃用
 折行以确保其不会超过 79 个字符
 这有助于小显示器用户阅读,也可以让大显示器能并排显示几个代码文件
 使用空行分隔函数和类,以及函数中的大块代码
 可能的话,注释独占一行
 使用文档字符串
 把空格放到操作符两边,以及逗号后面,但是括号里侧不加空格:a = f(1, 2) + g(3, 4)
 统一函数和类命名
 推荐类名用 驼峰命名, 函数和方法名用 小写_和_下划线。总是用 self 作为方法的第一个参数(关于类和方法的知识详见 初识类 )
 不要使用花哨的编码,如果你的代码的目的是要在国际化环境。Python 的默认情况下,UTF-8,甚至普通的 ASCII 总是工作的最好
 同样,也不要使用非 ASCII 字符的标识符,除非是不同语种的会阅读或者维护代码。

 任务评价

请学生按照下表中的要求完成本次评价,并在物理机桌面上以自己的两位学号+姓名的形式命名文件夹,保存所有截图软件,文件保存为jpeg或 png格式。
在这里插入图片描述

 任务拓展

1、 使用函数实现简单计算器。
2、 给计算器程序中的函数传递参数。
3、 使用Lambda实现计算器程序。
4、 给计算器程序增加文档字符串和注解。

任务2.5 使用模块

任务描述
公司接到一个项目需要使用Python进行编程,项目经理布置任务需要我们小组进行编程的准备并写出一个例子程序。请大家和我一起熟悉python模块的使用,进行准备并使用Python编程。
任务分析
python模块的使用包括以下几个方面:
 模块—可重用的Python代码块
 标准模块—纳入Python标准的Python可重用代码块
 包—系列相关的可重用代码块的容身之地
任务实施

2.5.1 模块

1)模块初步

如果你退出 Python 解释器并重新进入,你做的任何定义(变量和方法)都会丢失。因此,如果你想要编写一些更大的程序,为准备解释器输入使用一个文本编辑器会更好,并以那个文件替代作为输入执行。这就是传说中的 脚本。随着你的程序变得越来越长,你可能想要将它分割成几个更易于维护的文件。你也可能想在不同的程序中使用顺手的函数,而不是把代码在它们之间中拷来拷去。
为了满足这些需要,Python 提供了一个方法可以从文件中获取定义,在脚本或者解释器的一个交互式实例中使用。这样的文件被称为 模块;模块中的定义可以 导入 到另一个模块或 主模块 中(在脚本执行时可以调用的变量集位于最高级,并且处于计算器模式)。
模块是包括 Python 定义和声明的文件。文件名就是模块名加上 .py 后缀。模块的模块名(做为一个字符串)可以由全局变量 name 得到。例如,你可以用自己惯用的文件编辑器在当前目录下创建一个叫 fibo.py 的文件,录入如下内容,如图2-5-1所示。
在这里插入图片描述

图2-5-1 模块

现在进入 Python 解释器并使用以下命令导入这个模块:

import fibo

这样做不会直接把 fibo 中的函数导入当前的语义表;它只是引入了模块名 fibo。你可以通过模块名按如下方式访问这个函数,如图2-4-22所示。
在这里插入图片描述

图2-5-22 导入模块

如果打算频繁使用一个函数,你可以将它赋予一个本地变量,如图2-4-23所示。
在这里插入图片描述

图2-5-23 赋予本地变量

2)深入模块

除了包含函数定义外,模块也可以包含可执行语句。这些语句一般用来初始化模块。他们仅在第一次被导入的地方执行一次。

每个模块都有自己私有的符号表,被模块内所有的函数定义作为全局符号表使用。因此,模块的作者可以在模块内部使用全局变量,而无需担心它与某个用户的全局变量意外冲突。从另一个方面讲,如果你确切的知道自己在做什么,你可以使用引用模块函数的表示法访问模块的全局变量,modname.itemname。

模块可以导入其他的模块。一个(好的)习惯是将所有的 import 语句放在模块的开始(或者是脚本),这并非强制。被导入的模块名会放入当前模块的全局符号表中。

import 语句的一个变体直接从被导入的模块中导入命名到本模块的语义表中,如图2-4-24所示。
在这里插入图片描述

图2-5-24 模块中导入

这样不会从局域语义表中导入模块名(如上所示, fibo 没有定义)。

甚至有种方式可以导入模块中的所有定义,如图2-4-25所示。
在这里插入图片描述

图2-5-25 导入模块中的所有定义

这样可以导入所有除了以下划线( _ )开头的命名。
需要注意的是在实践中往往不鼓励从一个模块或包中使用 * 导入所有,因为这样会让代码变得很难读。不过,在交互式会话中这样用很方便省力。
出于性能考虑,每个模块在每个解释器会话中只导入一遍。因此,如果你修改了你的模块,需要重启解释器;或者,如果你就是想交互式的测试这么一个模块,可以用 imp.reload() 重新加载,例如 import imp; imp.reload(modulename)。

3)作为脚本来执行模块

当你使用以下方式运行 Python 模块时,模块中的代码便会被执行:

python fibo.py <arguments>

模块中的代码会被执行,就像导入它一样,不过此时 name 被设置为 “main”。这相当于,如果你在模块后加入如下代码:

if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

就可以让此文件像作为模块导入时一样作为脚本执行。此代码只有在模块作为 “main” 文件执行时才被调用:

$ python fibo.py 50
1 1 2 3 5 8 13 21 34

如果模块被导入,不会执行这段代码:

>>> import fibo
>>>

这通常用来为模块提供一个便于测试的用户接口(将模块作为脚本执行测试需求)。

4)模块的搜索路径

导入一个叫 spam 的模块时,解释器先在当前目录中搜索名为 spam.py 的文件。如果没有找到的话,接着会到 sys.path 变量中给出的目录列表中查找。 sys.path 变量的初始值来自如下:

 输入脚本的目录(当前目录)。
 环境变量 PYTHONPATH 表示的目录列表中搜索
 (这和 shell 变量 PATH 具有一样的语法,即一系列目录名的列表)。
 Python 默认安装路径中搜索。

在支持符号连接的文件系统中,输入的脚本所在的目录是符号连接指向的目录。 换句话说也就是包含符号链接的目录不会被加到目录搜索路径中。
实际上,解释器由 sys.path 变量指定的路径目录搜索模块,该变量初始化时默认包含了输入脚本(或者当前目录), PYTHONPATH 和安装目录。这样就允许 Python 程序了解如何修改或替换模块搜索目录。需要注意的是由于这些目录中包含有搜索路径中运行的脚本,所以这些脚本不应该和标准模块重名,否则在导入模块时 Python 会尝试把这些脚本当作模块来加载。这通常会引发错误。请参见 标准模块 以了解更多的信息。

2.5.2 标准模块

Python 带有一个标准模块库,并发布有独立的文档,名为 Python 库参考手册(此后称其为“库参考手册”)。有一些模块内置于解释器之中,这些操作的访问接口不是语言内核的一部分,但是已经内置于解释器了。这既是为了提高效率,也是为了给系统调用等操作系统原生访问提供接口。这类模块集合是一个依赖于底层平台的配置选项。例如,winreg 模块只提供在 Windows 系统上才有。有一个具体的模块值得注意: sys ,这个模块内置于所有的 Python 解释器。变量 sys.ps1 和 sys.ps2 定义了主提示符和辅助提示符字符串,下面在DOS命令行窗口进行演示,如图2-4-26所示。
在这里插入图片描述

图2-5-26 DOS命令窗口设定Python提示符

这两个变量只在解释器的交互模式下有意义。

变量 sys.path 是解释器模块搜索路径的字符串列表。它由环境变量 PYTHONPATH 初始化,如果没有设定 PYTHONPATH ,就由内置的默认值初始化。你可以用标准的字符串操作修改它,下面在DOS命令行窗口进行演示,如图2-4-27所示。
在这里插入图片描述

图2-5-27 DOS命令窗口设定PYTHONPATH

dir() 函数

内置函数 dir() 用于按模块名搜索模块定义,它返回一个字符串类型的存储列表,如图2-4-28所示。
在这里插入图片描述

图2-5-28 dir

无参数调用时,dir() 函数返回当前定义的命名,如图2-4-29所示。
在这里插入图片描述

图2-5-29无参数调用

注意该列表列出了所有类型的名称:变量,模块,函数,等等。

dir() 不会列出内置函数和变量名。如果你想列出这些内容,它们在标准模块 builtins 中定义,如图2-4-30所示。
在这里插入图片描述

图2-5-30 内置函数和变量名

2.5.3 包

包通常是使用用“圆点模块名”的结构化模块命名空间。例如,名为 A.B 的模块表示了名为 A 的包中名为 B 的子模块。正如同用模块来保存不同的模块架构可以避免全局变量之间的相互冲突,使用圆点模块名保存像 NumPy 或 Python Imaging Library 之类的不同类库架构可以避免模块之间的命名冲突。

假设你现在想要设计一个模块集(一个“包”)来统一处理声音文件和声音数据。存在几种不同的声音格式(通常由它们的扩展名来标识,例如:.wav, .aiff,.au ),于是,为了在不同类型的文件格式之间转换,你需要维护一个不断增长的包集合。可能你还想要对声音数据做很多不同的操作(例如混音,添加回声,应用平衡 功能,创建一个人造效果),所以你要加入一个无限流模块来执行这些操作。你的包可能会是这个样子(通过分级的文件体系来进行分组):

sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  Subpackage for sound effects
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  Subpackage for filters
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

当导入这个包时,Python 通过 sys.path 搜索路径查找包含这个包的子目录。
为了让 Python 将目录当做内容包,目录中必须包含 init.py 文件。这是为了避免一个含有烂俗名字的目录无意中隐藏了稍后在模块搜索路径中出现的有效模块,比如 string。最简单的情况下,只需要一个空的 init.py 文件即可。当然它也可以执行包的初始化代码,或者定义稍后介绍的 all 变量。

用户可以每次只导入包里的特定模块,例如:

 import sound.effects.echo
这样就导入了 sound.effects.echo 子模块。它必需通过完整的名称来引用:
 sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
导入包时有一个可以选择的方式:
 from sound.effects import echo
这样就加载了 echo 子模块,并且使得它在没有包前缀的情况下也可以使用,所以它可以如下方式调用:
 echo.echofilter(input, output, delay=0.7, atten=4)
还有另一种变体用于直接导入函数或变量:
 from sound.effects.echo import echofilter
这样就又一次加载了 echo 子模块,但这样就可以直接调用它的 echofilter() 函数:
 echofilter(input, output, delay=0.7, atten=4)
需要注意的是使用 from package import item 方式导入包时,这个子项(item)既可以是包中的一个子模块(或一个子包),也可以是包中定义的其它命名,像函数、类或变量。import 语句首先核对是否包中有这个子项,如果没有,它假定这是一个模块,并尝试加载它。如果没有找到它,会引发一个 ImportError 异常。

相反,使用类似 import item.subitem.subsubitem 这样的语法时,这些子项必须是包,最后的子项可以是包或模块,但不能是前面子项中定义的类、函数或变量。

从 * 导入包

那么当用户写下 from sound.effects import * 时会发生什么事?理想中,总是希望在文件系统中找出包中所有的子模块,然后导入它们。这可能会花掉很长时间,并且出现期待之外的边界效应,导出了希望只能显式导入的包。
对于包的作者来说唯一的解决方案就是给提供一个明确的包索引。import 语句按如下条件进行转换:执行 from package import * 时,如果包中的 init.py 代码定义了一个名为 all 的列表,就会按照列表中给出的模块名进行导入。新版本的包发布时作者可以任意更新这个列表。如果包作者不想 import * 的时候导入他们的包中所有模块,那么也可能会决定不支持它( import * )。例如, sound/effects/init.py 这个文件可能包括如下代码:

__all__ = ["echo", "surround", "reverse"]

这意味着 from sound.effects import * 语句会从 sound 包中导入以上三个已命名的子模块。

如果没有定义 all , from sound.effects import * 语句 不会 从 sound.effects 包中导入所有的子模块。无论包中定义多少命名,只能确定的是导入了 sound.effects 包(可能会运行 init.py 中的初始化代码)以及包中定义的所有命名会随之导入。这样就从 init.py 中导入了每一个命名(以及明确导入的子模块)。同样也包括了前述的 import 语句从包中明确导入的子模块,考虑以下代码:

import sound.effects.echo
import sound.effects.surround
from sound.effects import *

在这个例子中,echo 和 surround 模块导入了当前的命名空间,这是因为执行 from…import 语句时它们已经定义在 sound.effects 包中了(定义了 all 时也会同样工作)。

尽管某些模块设计为使用 import * 时它只导出符合某种规范/模式的命名,仍然不建议在生产代码中使用这种写法。

记住,from Package import specific_submodule 没有错误!事实上,除非导入的模块需要使用其它包中的同名子模块,否则这是推荐的写法。

包内引用

如果包中使用了子包结构(就像示例中的 sound 包),可以按绝对位置从相邻的包中引入子模块。例如,如果 sound.filters.vocoder 包需要使用 sound.effects 包中的 echo 模块,它可以 from sound.Effects import echo。

你可以用这样的形式 from module import name 来写显式的相对位置导入。那些显式相对导入用点号标明关联导入当前和上级包。以 surround 模块为例,你可以这样用:

from . import echo
from .. import formats
from ..filters import equalizer

需要注意的是显式或隐式相对位置导入都基于当前模块的命名。因为主模块的名字总是 “main”,Python 应用程序的主模块应该总是用绝对导入。

多重目录中的包

包支持一个更为特殊的特性, path。 在包的 init.py 文件代码执行之前,该变量初始化一个目录名列表。该变量可以修改,它作用于包中的子包和模块的搜索功能。

这个功能可以用于扩展包中的模块集,不过它不常用。

 相关知识

Python3 标准库概览
1、操作系统接口
os模块提供了不少与操作系统相关联的函数。

>>> import os
>>> os.getcwd()      # 返回当前的工作目录
'C:\\Python34'
>>> os.chdir('/server/accesslogs')   # 修改当前的工作目录
>>> os.system('mkdir today')   # 执行系统命令 mkdir 

建议使用 “import os” 风格而非 “from os import *”。这样可以保证随操作系统不同而有所变化的 os.open() 不会覆盖内置函数 open()。
在使用 os 这样的大型模块时内置的 dir() 和 help() 函数非常有用:

>>> import os
>>> dir(os)
<returns a list of all module functions>
>>> help(os)
<returns an extensive manual page created from the module's docstrings>
#针对日常的文件和目录管理任务,:mod:shutil 模块提供了一个易于使用的高级接口:
>>> import shutil
>>> shutil.copyfile('data.db', 'archive.db')
>>> shutil.move('/build/executables', 'installdir')

2、文件通配符
glob模块提供了一个函数用于从目录通配符搜索中生成文件列表:

>>> import glob
>>> glob.glob('*.py')
['primes.py', 'random.py', 'quote.py']

3、命令行参数
通用工具脚本经常调用命令行参数。这些命令行参数以链表形式存储于 sys 模块的 argv 变量。例如在命令行中执行 “python demo.py one two three” 后可以得到以下输出结果:

>>> import sys
>>> print(sys.argv)
['demo.py', 'one', 'two', 'three']

4、错误输出重定向和程序终止
sys 还有 stdin,stdout 和 stderr 属性,即使在 stdout 被重定向时,后者也可以用于显示警告和错误信息。

>>> sys.stderr.write('Warning, log file not found starting a new one\n')
Warning, log file not found starting a new one

大多脚本的定向终止都使用 “sys.exit()”。

5、字符串正则匹配
re模块为高级字符串处理提供了正则表达式工具。对于复杂的匹配和处理,正则表达式提供了简洁、优化的解决方案:

>>> import re
>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']
>>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
'cat in the hat'
#如果只需要简单的功能,应该首先考虑字符串方法,因为它们非常简单,易于阅读和调试: 
>>> 'tea for too'.replace('too', 'two')
'tea for two'

6、数学
math模块为浮点运算提供了对底层C函数库的访问:

>>> import math
>>> math.cos(math.pi / 4)
0.70710678118654757
>>> math.log(1024, 2)
10.0
random提供了生成随机数的工具。
>>> import random
>>> random.choice(['apple', 'pear', 'banana'])
'apple'
>>> random.sample(range(100), 10)   # sampling without replacement
[30, 83, 16, 4, 8, 81, 41, 50, 18, 33]
>>> random.random()    # random float
0.17970987693706186
>>> random.randrange(6)    # random integer chosen from range(6)
4

7、访问互联网
有几个模块用于访问互联网以及处理网络通信协议。其中最简单的两个是用于处理从 urls 接收的数据的 urllib.request 以及用于发送电子邮件的 smtplib:

>>> from urllib.request import urlopen
>>> for line in urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl'):
...     line = line.decode('utf-8')  # Decoding the binary data to text.
...     if 'EST' in line or 'EDT' in line:  # look for Eastern Time
...         print(line)


Nov. 25, 09:43:32 PM EST

>>> import smtplib
>>> server = smtplib.SMTP('localhost')
>>> server.sendmail('soothsayer@example.org', 'jcaesar@example.org',
... """To: jcaesar@example.org
... From: soothsayer@example.org
...
... Beware the Ides of March.
... """)
>>> server.quit()

注意第二个例子需要本地有一个在运行的邮件服务器。

8、日期和时间
datetime模块为日期和时间处理同时提供了简单和复杂的方法。
支持日期和时间算法的同时,实现的重点放在更有效的处理和格式化输出。
该模块还支持时区处理:

>>> # dates are easily constructed and formatted
>>> from datetime import date
>>> now = date.today()
>>> now
datetime.date(2003, 12, 2)
>>> now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.")
'12-02-03. 02 Dec 2003 is a Tuesday on the 02 day of December.'

>>> # dates support calendar arithmetic
>>> birthday = date(1964, 7, 31)
>>> age = now - birthday
>>> age.days
14368

9、数据压缩
以下模块直接支持通用的数据打包和压缩格式:zlib,gzip,bz2,zipfile,以及 tarfile。

>>> import zlib
>>> s = b'witch which has which witches wrist watch'
>>> len(s)
41
>>> t = zlib.compress(s)
>>> len(t)
37
>>> zlib.decompress(t)
b'witch which has which witches wrist watch'
>>> zlib.crc32(s)
226805979

10、性能度量
有些用户对了解解决同一问题的不同方法之间的性能差异很感兴趣。Python 提供了一个度量工具,为这些问题提供了直接答案。
例如,使用元组封装和拆封来交换元素看起来要比使用传统的方法要诱人的多,timeit 证明了现代的方法更快一些。

>>> from timeit import Timer
>>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
0.57535828626024577
>>> Timer('a,b = b,a', 'a=1; b=2').timeit()
0.54962537085770791
相对于 timeit 的细粒度,:mod:profile 和 pstats 模块提供了针对更大代码块的时间度量工具。

11、测试模块
开发高质量软件的方法之一是为每一个函数开发测试代码,并且在开发过程中经常进行测试
doctest模块提供了一个工具,扫描模块并根据程序中内嵌的文档字符串执行测试。
测试构造如同简单的将它的输出结果剪切并粘贴到文档字符串中。
通过用户提供的例子,它强化了文档,允许 doctest 模块确认代码的结果是否与文档一致:

def average(values):
    """Computes the arithmetic mean of a list of numbers.

    >>> print(average([20, 30, 70]))
    40.0
    """
    return sum(values) / len(values)

import doctest
doctest.testmod()   # 自动验证嵌入测试

unittest模块不像 doctest模块那么容易使用,不过它可以在一个独立的文件里提供一个更全面的测试集:

import unittest

class TestStatisticalFunctions(unittest.TestCase):

    def test_average(self):
        self.assertEqual(average([20, 30, 70]), 40.0)
        self.assertEqual(round(average([1, 5, 7]), 1), 4.3)
        self.assertRaises(ZeroDivisionError, average, [])
        self.assertRaises(TypeError, average, 20, 30, 70)

unittest.main() # Calling from the command line invokes all tests

 任务评价

请学生按照下表中的要求完成本次评价,并在物理机桌面上以自己的两位学号+姓名的形式命名文件夹,保存所有截图软件,文件保存为jpeg或 png格式。
在这里插入图片描述

 任务拓展

1、使用os和sys模块编写一个程序
2、使用和网络相关的模块编写一个程序
3、使用数学模块编写计算器程序
4、使用random模块编写生成随机数程序

项目评价

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2231651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

less解决function中return写法在浏览器被识别成Object导致样式失败的问题

问题描述&#xff1a; 一开始写的是: baseFontSize: 37.5px;//基于屏幕尺寸/10得出的基准font-size// return失败,浏览器显示为[object Object],[object Object] .pxToRem(px){value: px / baseFontSize * 1rem;return value; } 使用height: .pxToRem(40px);之后浏览器却是这…

安装中文版 Matlab R2022a

下载安装包 压缩包有点大&#xff0c;大概20G 百度网盘&#xff1a;下载链接 提取码&#xff1a;rmja 安装 解压后打开目录&#xff0c;右键以管理员身份运行 setup.exe 选择输入安装秘钥 输入秘钥&#xff1a; 50874-33247-14209-37962-45495-25133-28159-33348-18070-6088…

Linux云计算 |【第五阶段】CLOUD-DAY9

主要内容&#xff1a; Metrics资源利用率监控、存储卷管理&#xff08;临时卷ConfitMap、EmptyDir、持久卷HostPath、NFS(PV/PVC)&#xff09; 一、Metrics介绍 metrics是一个监控系统资源使用的插件&#xff0c;可以监控Node节点上的CPU、内存的使用率&#xff0c;或Pod对资…

sql数据库数据修改与删除-DML

目录 修改数据 同时修改两个数据 修改表中所有数据 删除数据 删除指定字段的值&#xff08;用UPDATE&#xff09; 删除整张表的数据 举例表如下FIRST表 修改数据 UPDATE 表名 SET 字段名1值1,字段名2值2,...[WHERE 条件]; 将first表name字段张三修改为张三丰。 UPDA…

Oracle视频基础1.3.5练习

Oracle视频基础1.3.4练习 1.3.5 检查数据库启动状态 ps -ef | grep oracle ipcs clear演示alter向前向后改database阶段 sqlplus /nolog conn / as sysdba startup mount alter database nomount # 报错 alter database open启动restricted mode&#xff0c;创建一个connect&…

MySQL数据库迁移到DM8数据库

1. 达梦新建zsaqks库 2. 打开DM数据迁移工具 3. 新建工程 4. 迁移 - 右击 - 新建迁移 下一步 5. 选择迁移方式 6. MySQL数据源 请输入MySQL数据库信息 7. DM数据库目的 请输入达梦数据库信息 8. 迁移选项 保持对象名大小写(勾选) 9. 指定模式 指定是从数据源复制对象。 10.…

如何在Linux系统中使用Ansible进行自动化部署

如何在Linux系统中使用Ansible进行自动化部署 Ansible简介 安装Ansible 在Debian/Ubuntu系统中安装 在CentOS/RHEL系统中安装 启动Ansible服务 Ansible基本概念 Inventory Playbook Module 配置Ansible 测试Ansible配置 执行Ansible Playbook Ansible模块 文件模块 包管理模块…

爬虫学习2

数据解析 正则表达式 量词&#xff1a; import re#searcch只会匹配到第一次匹配的内容#result re.search(r"\d","今年32")#print(result.group()) #result re.findall(r"\d","我是一个abcdeafg") #print(result)#search只会匹配到第…

初步认识Java,及使用

JAVA 特点 简单性 面向对象 分布式 健壮性 安全性 体系结构中立&#xff08;平台无关&#xff09; 可移植性 解释执行 高性能 多线程 动态 发展史 JDK&#xff0c;Eclipse下载&#xff0c;…

牛客sql题目总结(1)

1.第N高的薪水 AC: create function getnthhighestsalary(n int) returns int begindeclare m int; set m n - 1; return (select distinct salaryfrom employeeorder by salary desclimit m, 1); end 2. 3. 4. 5. 6.

Pr 视频效果:ASC CDL

视频效果/颜色校正/ASC CDL Color Correction/ASC CDL ASC CDL ASC CDL效果通过对红、绿、蓝三个原色通道的独立调整&#xff0c;实现对图像色彩的精确控制。在此基础上&#xff0c;还可用于调整处理后图像的整体饱和度。 ◆ ◆ ◆ 效果选项说明 斜率 Slope、偏移 Offset和功…

开源OCR免费助力法律文档数字化,提升文档管理效率

一、在法律行业&#xff0c;每天需要处理大量纸质文件&#xff0c;从合同到判决书&#xff0c;手动录入不仅费时&#xff0c;还容易出错。为解决这一问题推出了一款免费开源的OCR智能识别平台&#xff0c;通过先进的光学字符识别&#xff08;OCR&#xff09;技术&#xff0c;将…

RAG流程

目录 1. 前言2. 流程详解2.1 知识管理2.1.1 知识存储【未展开】2.1.2 知识加载(1) docx(2) pdf 2.2 切分2.2.1 固定长度分割2.2.2 自己写的固定分块方法 2.3 创建知识库的向量库2.4 检索2.5 模型部署和加载&#xff08;1&#xff09;api生成&#xff08;2&#xff09;Transform…

JeecgBoot入门

最近在了解低代码平台&#xff0c;其中关注到gitee上开源项目JeecgBoot&#xff0c;JeecgBoot官方也有比较完整的入门教学文档&#xff0c;这里我们将耕者官方教程学习&#xff0c;并将其记录下来。 一、项目简介 JeecgBoot 是一款基于代码生成器的低代码开发平台拥有零代码能力…

threejs开源实例-粒子地球

源码 three.js webgl - geometry - cube <script type"module">import * as THREE from "three";import { OrbitControls } from "three/addons/controls/OrbitControls.js";import { GUI } from "three/addons/libs/lil-gui.modul…

11.1 daimayuan 模拟赛总结

逆天 复盘 7:40 开题 扫了一眼四个题&#xff0c;T1 神秘构造&#xff0c;感觉和以前做过的某道题有点像啊&#xff0c;应该能做&#xff1b;T2 题意很简洁&#xff0c;感觉可做&#xff1b;T3&#xff0c;一眼感觉是什么优化 dp&#xff1b;T4&#xff0c;看上去像是拆期望…

2024年,Rust开发语言,现在怎么样了?

Rust开发语言有着一些其他语言明显的优势&#xff0c;但也充满着争议&#xff0c;难上手、学习陡峭等。 Rust 是由 Mozilla 主导开发的通用、编译型编程语言&#xff0c;2010年首次公开。 在 Stack Overflow 的年度开发者调查报告中&#xff0c;Rust 连续多年被评为“最受喜爱…

Golang | Leetcode Golang题解之第528题按权重随机选择

题目&#xff1a; 题解&#xff1a; type Solution struct {pre []int }func Constructor(w []int) Solution {for i : 1; i < len(w); i {w[i] w[i-1]}return Solution{w} }func (s *Solution) PickIndex() int {x : rand.Intn(s.pre[len(s.pre)-1]) 1return sort.Searc…

微服务day02

教学文档&#xff1a; 黑马教学文档 Docker Docker的安装 镜像和容器 命令解读 常见命令 案例 查看DockerHub&#xff0c;拉取Nginx镜像&#xff0c;创建并运行容器 搜索Nginx镜像&#xff1a;在 www.hub.docker.com 网站进行查询 拉取镜像&#xff1a; docker pull ngin…

认证鉴权框架之—sa-token

一、概述 Satoken 是一个 Java 实现的权限认证框架&#xff0c;它主要用于 Web 应用程序的权限控制。Satoken 提供了丰富的功能来简化权限管理的过程&#xff0c;使得开发者可以更加专注于业务逻辑的开发。 二、逻辑流程 1、登录认证 &#xff08;1&#xff09;、创建token …