当前位置: 首页 > news >正文

1--Python基础课程实验指导书

在这里插入图片描述

**

1.1实验介绍

**

1.1.1 知识点

• 使用交互模式的 Python3 解释器
• 简单使用 vim 编写 Python3 脚本
• 执行 Python3 脚本
• Python3 代码风格建议
• Python3 中使用注释
• 认识 Python3 模块

1.1.2 实验环境

• Python 3.6
• 终端
• 维姆

1.2解释器

Python 是一个脚本语言,你可以在 Python 解释器中直接写代码或者将代码写到一个文件里,然后执行这个文件(即脚本文件)。
首先,我们从使用解释器开始,打开终端,键入 并回车。这个时候解释器便工作于交互模式。python3
在这里插入图片描述

作为我们第一个 Python 代码,我们将打印经典的 “Hello World!”,输入,如下所示:python3
>>> print("Hello World!")
Hello World!

欣赏完自己的杰作后,按 输入一个 EOF 字符来退出解释器,你也可以键入 来退出解释器。Ctrl + Dexit()
1.3脚本文件
作为正式的程序员,你可能想要将上述的代码写到一个源文件。那么我们来创建一个 helloworld.py 文件,用你喜欢的任何编辑器来创建这个文件我们建议使用 Vim。
首先,创建一个文件夹来存放之后的文件:wiseinsight
sudo mkdir /home/wiseinsight
进入 目录下:wiseinsight
cd /home/wiseinsight/
打开终端,键入 来启动 Vim 并编辑 helloworld.py,启动后不要乱按键。sudo vim helloworld.py
在这里插入图片描述

然后按 键进入插入模式,此时你可以看到左下角有 “INSERT” 这个单词,现在你可以键入下面的代码了。i
#!/usr/bin/env python3
print(“Hello World!”)
其中第一行的前两个字符 称为Shebang ,目的是告诉 shell 使用 Python 解释器执行其下面的代码。#!
在这里插入图片描述

然后按 键退出插入模式,再键入 回车,Vim 就会保存文件并退出。Esc:wq
要运行脚本文件 ,还要为文件添加可执行权限(否则会出现权限不足的错误):
helloworld.py
sudo chmod +x helloworld.py
在这里使用到了linux下的chmod命令来变更文件或目录的权限,代表赋予了其可执行的权限。+x
然后执行脚本文件:
./helloworld.py
在这里插入图片描述

这里需要注意如果程序中没有 的话,应该使用 来执行,否则使用 程序会被当作 bash 脚本来执行,最终报错。#!/usr/bin/env python3python3 helloworld.py./helloworld.py

1.4代码风格建议

在 Python中,空格很重要,我们使用空格将标识符区分开,行开始处的空格我们称之为缩进,如果你的缩进是错误的,Python 解释器会抛出错误。例如下面情形:
在这里插入图片描述

这是因为第二行开始处出现了多余的空格,所以需要经常检查代码的缩进。
如果你在代码中混用制表符和空格,这种缩进错误会很常见。
所以如果是用空格,就一直用空格缩进,不要使用制表符。
建议遵守以下约定:
• 使用 4 个空格来缩进
• 永远不要混用空格和制表符
• 在函数之间空一行
• 在类之间空两行
• 字典,列表,元组以及参数列表中,在 后添加一个空格。对于字典, 后面也添加一个空格,:
• 在赋值运算符和比较运算符周围要有空格(参数列表中除外),但是括号里则不加空格:a = f(1, 2) + g(3, 4)

1.5注释

注释是一些文本用来解释此处代码是做什么的,写注释是为了使他人更容易理解代码。
Python 的注释以 #字符开始的,在 #字符到行尾之间的所有东西都被程序忽略为注释,也就说对程序没有任何影响。
在这里插入图片描述

注释主要面向的人群是开发人员和维护代码库的人员,所以如果你写了一些复杂代码,你应该写足够的注释在里面,以便让其他任何人能够通过你的注释读懂代码。你应该总是在 后跟一个空格,然后再写注释。你也可以做一些标准的注释,像下面这样。#
#FIXME – fix these code later
#TODO – in future you have to do this

1.6模块

模块是包含了我们能复用的代码的文件,包含了不同的函数定义,变量。模块文件通常以 .py 为扩展名。
Python 本身在默认安装时就带有大量的模块。我们之后将会用到其中的一部分。在使用模块前先导入它。
在这里插入图片描述

我们会在模块这个实验里学习更多有关模块的知识。

1.7总结

完成本实验后,应当明白如何使用交互模式的 Python3 解释器,如何简单使用 vim 编写脚本文件并执行这个脚本文件。
要特别注意的是,Python 使用缩进来定义语句块,缩进是 Python 语法的一部分,这与其它大多数语言不同。
代码风格在本课程的实验 有更为详细的讲述。注释的话,能使用英文建议使用英文。模块同样会在之后的实验里深入学习。

2.1实验介绍

本节实验内容主要包括 Python 基本的数据类型和变量。

2.1.1 知识点

• python 关键字
• 变量的定义与赋值
• input() 函数
• 字符串的格式化

2.2关键字和标识符

每一种编程语言都有它们自己的语法规则,就像我们所说的外语。
下列的标识符是 Python3 的关键字,并且不能用于通常的标识符。关键字必须完全按照下面拼写:
False def if raise
None del import return
True elif in try
and else is while
as except lambda with
assert finally nonlocal yield
break for not
class from or
continue global pass
这些内容可以在 Python3 解释器中得到:
python3里面输入:
help()
在这里插入图片描述

在 Python 中 我们不需要为变量指定数据类型。所以你可以直接写出 ,这样变量 就是整数类型。如果你写出 ,那么变量 就是浮点类型。abc = 1abcabc = 1.0abc
在这里插入图片描述

通过上面的例子你应该理解了如何在 Python 中定义变量,也就是只需要输入变量名和值就行了。Python 也能操作字符串,它们用单引号或双引号括起来,就像下面这样。
在这里插入图片描述

2.3从键盘读取输入

通常情况下,Python 的代码中是不需要从键盘读取输入的。不过我们还是可以在 Python 中使用函数 来做到这一点, 有一个用于打印在屏幕上的可选字符串参数,返回用户输入的字符串。input()input()
我们来写一个程序,它将会从键盘读取一个数字并且检查这个数字是否小于 100。这个程序名称是 。还记得如何使用 Vim 吗?打开终端,使用 Vim 开始编写代码:/home/wiseinsight/testhundred.py
在目录下的终端中输入:wiseinsight
sudo vim testhundred.py
输入后,编写以下代码:i
#!/usr/bin/env python3
number = int(input("Enter an integer: "))
if number <= 100:
print(“Your number is less than or equal to 100”)
else:
print(“Your number is greater than 100”)
注意缩进!复制粘贴过去会有缩进会有问题,之后的代码也一样要注意。
接着按 键并输入 退出Vim。ESC:wq
该段代码的含义如下:
如果 小于等于 100,输出 “您的号码小于或等于 100”,如果大于 100,输出 “您的号码大于 100”。number
在执行程序前,别忘了为文件添加可执行权限:
sudo chmod +x testhundred.py
运行程序:
./testhundred.py
程序运行起来就像这样:
在这里插入图片描述

后续程序中将会用到之后实验将学到的 while 循环语句,这里先简单介绍下。
while 是使用一个表达式作为判断的条件,如果条件不能够达成则停止循环:
w = 20
while w > 1:
print(w)
w -= 1
这个循环中判断条件为 ,当条件不满足的时候就停止循环。当 w 的值小于等于 1 的时候,循环退出。这里要注意 ,等同于 。w > 1w -= 1w = w - 1
下一个程序我们写入 来计算投资:/home/wiseinsight/investment.py
终端输入:
sudo vim /home/wiseinsight/investment.py
用Vim 打开,写入以下代码:
#!/usr/bin/env python3

#!/usr/bin/env python3
amount = float(input("Enter amount: "))  # 输入数额
inrate = float(input("Enter Interest rate: "))  # 输入利率
period = int(input("Enter period: "))  # 输入期限
value = 0
year = 1
while year <= period:value = amount + (inrate * amount)print("Year {} Rs. {:.2f}".format(year, value))amount = valueyear = year + 1

Vim编写保存后要记得改权限(之后不再演示)
sudo chmod +x investment.py
运行程序:
在这里插入图片描述

$ cd /home/wiseinsight
$ chmod +x investment.py
$ ./investment.py
Enter amount: 10000
Enter Interest rate: 0.14
Enter period: 5
Year 1 Rs. 11400.00
Year 2 Rs. 12996.00
Year 3 Rs. 14815.44
Year 4 Rs. 16889.60
Year 5 Rs. 19254.15

while year <= period:的意思是,当 的值小于等于 的值时,下面的语句将会一直循环执行下去,直到 大于 时停止循环。yearperiodyearperiod
Year {} Rs. {:.2f}".format(year, value)称为字符串格式化,大括号和其中的字符会被替换成传入 的参数,也即 和 。其中 的意思是替换为 2 位精度的浮点数。str.format()yearvalue{:.2f}

2.4代码示例

一些关于变量和数据类型的代码实例。下面的例子程序请都写在 目录下。/home/wiseinsight
本部分包括下面的几个实例:

  1. 求 N 个数字的平均值
  2. 华氏温度到摄氏温度转换程序
    请按照指定目录完成每个程序,并理解每个程序中每行代码的含义。

2.4.1 求 N 个数字的平均值

下面的程序用来求 N 个数字的平均值。
请将程序代码写入到文件 中,程序中将需要输入 10 个数字,最后计算 10 个 数字的平均值。/home/ wiseinsight/averagen.py
代码如下:

#!/usr/bin/env python3
N = 10
sum = 0
count = 0
print("please input 10 numbers:")
while count < N:number = float(input())sum = sum + numbercount = count + 1
average = sum / N
print("N = {}, Sum = {}".format(N, sum))
print("Average = {:.2f}".format(average))

运行程序过程,需要输入 10 个数字:
在这里插入图片描述

2.4.2 温度转换

在下面的程序里,我们使用公式 C = (F - 32) / 1.8 将华氏温度转为摄氏温度。
Vim编辑文件temperature.py

#!/usr/bin/env python3
fahrenheit = 0
print("Fahrenheit Celsius")
while fahrenheit <= 250:celsius = (fahrenheit - 32) / 1.8 # 转换为摄氏度print("{:5d} {:7.2f}".format(fahrenheit , celsius))fahrenheit = fahrenheit + 25

{:5d}的意思是替换为 5 个字符宽度的整数,宽度不足则使用空格填充。
的意思是替换为为7个字符宽度的保留两位的小数,小数点也算一个宽度,宽度不足则使用空格填充。其中指宽度为7,指保留两位小数。{:7.2f}7.2f
运行程序:
cd /home/wiseinsight
sudo chmod +x temperature.py
./temperature.py
输出结果:
在这里插入图片描述

2.5单行定义多个变量或赋值

你甚至可以在一行内将多个值赋值给多个变量。
在终端中输入:
python3
进入到 python3 交互式界面:

a , b = 45, 54
a
45
b
54
在这里插入图片描述

这个技巧用来交换两个数的值非常方便。

a, b = b , a
a
54
b
45
在这里插入图片描述

要明白这是怎么工作的,你需要学习元组(tuple)这个数据类型。我们是用逗号创建元组。在赋值语句的右边我们创建了一个元组,我们称这为元组封装(tuple packing),赋值语句的左边我们则做的是元组拆封 (tuple unpacking)。
下面是另一个元组拆封的例子:

data = (“wiseinsight”, “China”, “Python”)
name, country, language = data
name
‘wiseinsight’
country
‘China’
language
‘Python’
在这里插入图片描述

2.6总结

完成这个实验我们应该了解到以下的内容:

  1. Python3 关键字有哪些(在这里不要求全部记住)
  2. 变量如何赋值变量
  3. Python3 怎样从键盘读取输入
  4. Python3 字符串的格式化
  5. 元组封装和拆封
    在这里可以了解更多有关字符串格式化的信息:https://docs.python.org/3/library/string.html#formatstrings。

3.1实验介绍

在 Python 中你会写大量的表达式。
表达式由运算符和操作数组成,像 就是一个表达式,其中 2 和 3 是操作数,加号是运算符。2+3
本节实验中我们将学习运算符和表达式的基本用法。

3.1.1 知识点

• 关系/逻辑运算
• 表达式
• 类型转换
3.2运算符介绍
运算符是一些符号,它告诉 Python 解释器去做一些数学或逻辑操作。一些基本的数学操作符如下所示:

2 + 3
5
23.0 - 3
20.0
22 / 12
1.8333333333333333
在这里插入图片描述

只要有任意一个操作数是浮点数,结果就会是浮点数。
进行除法运算时若是除不尽,结果将会是小数,这很自然,如果要进行整除,使用 运算符,它将返回商的整数部分。//
%是求余运算符:

14 % 3
2

3.2.1 整数运算示例

整数运算符比较容易理解,代码如下:
#!/usr/bin/env python3
days = int(input("Enter days: "))
months = days // 30
days = days % 30
print(“Months = {} Days = {}”.format(months, days))
在终端里使用Vim输入上述代码:sudo vim interger.py
所有示例都在目录下/home/wiseinsight/
用命令赋予可执行权限,最后运行程序:chmod
在这里插入图片描述

在后获得用户输入的天数,然后获得月份数和天数,最后把这些数打印出来。你可以使用更容易的办法:Enter days:
#!/usr/bin/env python3
days = int(input("Enter days: "))
print(“Months = {} Days = {}”.format(divmod(days, 30)))
divmod(num1, num2)函数返回一个元组,这个元组包含两个值,第一个是 num1 和 num2 相整除得到的值,第二个是 num1 和 num2 求余得到的值,然后我们用 运算符拆封这个元组,得到这两个值。

3.2.2 关系运算符

你可以使用下面的运算符实现关系运算。
关系运算符
算子 意义
< 小于
<= 小于等于

大于
= 大于等于
== 等于
!= 不等于
在终端里输入进入交互页面,试一试以下一些例子:python3

1 < 2
True
3 > 34
False
23 == 45
False
34 != 323
True
在这里插入图片描述

3.2.3 逻辑运算符

对于逻辑 与,或,非,我们使用 ,, 这几个关键字。andornot
逻辑运算符 和 也称作短路运算符:它们的参数从左向右解析,一旦结果可以确定就停止。例如,如果 和 为真而 为假, 不会解析 。作用于一个普通的非逻辑值时,短路运算符的返回值通常是能够最先确定结果的那个操作数。andorACBA and B and CC
关系运算可以通过逻辑运算符 和 组合,比较的结果可以用 来取反意。逻辑运算符的优先级又低于关系运算符,在它们之中, 具有最高的优先级, 优先级最低,所以 等于 。当然,括号也可以用于比较表达式。andornotnotorA and not B or C(A and (notB)) or C
下面是一些例子:

5 and 4 # 首先判断5,肯定为true,那么最终的结果就取决于 and 后面那个的布尔值,4 的布尔值为 true,这样就可以确定整个表达式的值为 true 了,所以返回 4
4
0 and 4 # 首先判断0,因为 0 的布尔值为 false,那么不管 and 后面那个的布尔值是什么,整个表达式的布尔值都应该为 false 了,这个时候就不需要判断 4 了,直接返回最先确定结果的那个数也就是0
0
False or 3 or 0
3
2 > 1 and not 3 > 5 or 4
True
在这里插入图片描述

3.2.4 简写运算符

x op= expression为简写运算的语法形式。其等价于x = x op 表达式,举例如下:

a = 12
a += 13
a
25
a /= 3
a
8.333333333333334
a += (26 * 32)
a
840.3333333333334
在这里插入图片描述

输入退出python交互页面,quit()
示例位置 ,/home/wiseinsight/shorthand.py
用Vim写入以下代码:
#!/usr/bin/env python3
N = 100
a = 2
while a < N:
print(str(a))
a *= a
运行程序:
cd /home/wiseinsight
sudo chmod +x shorthand.py
./shorthand.py
在这里插入图片描述

3.3表达式

通常我们书写表达式的时候,会在每一个运算符左右都放一个空格,这样使代码更可读,如:
a = 234 * (45 - 56 / 34)
一个用于展示表达式的例子,注意其中运算符的优先级。
#!/usr/bin/env python3
a = 9
b = 12
c = 3
x = a - b / 3 + c * 2 - 1
y = a - b / (3 + c) * (2 - 1)
z = a - (b / (3 + c) * 2) - 1
print("X = ", x)
print("Y = ", y)
print("Z = ", z)
运行程序:
cd /home/wiseinsight
sudo chmod +x evaluationexp.py
./evaluationexp.py
在这里插入图片描述

第一个计算的是x,步骤如下:
9 - 12 / 3 + 3 * 2 -1
9 - 4 + 3 * 2 - 1
9 - 4 + 6 - 1
5 + 6 - 1
11 - 1
10
由于括号的存在,y和z的计算方式不同,你可以自己去验证它们。

3.4类型转换

我们可以手动的执行类型转换。
类型转换函数 转换路径
float(string) 字符串 -> 浮点值
int(string) 字符串 -> 整数值
str(integer) 整数值 -> 字符串
str(float) 浮点值 -> 字符串

a = 8.126768
str(a)
‘8.126768’
在这里插入图片描述

可以分别尝试下前面的四个类型转换函数。

3.5程序示例

3.5.1 evaluateequ.py

这个程序计算数列1/x+1/(x+1)+1/(x+2)+ … +1/n,我们设 x = 1,n = 10。
使用Vim写入以下代码:
#!/usr/bin/env python3
sum = 0
for i in range(1, 11):
sum += 1.0 / i
print(“{:2d} {:6.4f}”.format(i , sum))
运行程序:
在这里插入图片描述

3.5.2 quadraticequation.py

这个程序的名称为 组合,是二次方程的英文词组。quadratic equation
这个程序用来求解二次方程式:
#!/usr/bin/env python3
import math
a = int(input("Enter value of a: "))
b = int(input("Enter value of b: "))
c = int(input("Enter value of c: "))
d = b * b - 4 * a * c
if d < 0:
print(“ROOTS are imaginary”)
else:
root1 = (-b + math.sqrt(d)) / (2 * a)
root2 = (-b - math.sqrt(d)) / (2 * a)
print("Root 1 = ", root1)
print("Root 2 = ", root2)
运行程序:
在这里插入图片描述

3.5.3 salesmansalary.py

这个程序计算一位数码相机销售人员的工资。他的基本工资是 1500,每售出一台相机他可以得到 200 并且获得 2% 的抽成。程序要求输入相机数量及单价。
#!/usr/bin/env python3
basic_salary = 1500
bonus_rate = 200
commission_rate = 0.02
numberofcamera = int(input("Enter the number of inputs sold: "))
price = float(input("Enter the price of camera: "))
bonus = (bonus_rate * numberofcamera)
commission = (commission_rate * price * numberofcamera)
print(“Bonus = {:6.2f}”.format(bonus))
print(“Commission = {:6.2f}”.format(commission))
print(“Gross salary = {:6.2f}”.format(basic_salary + bonus + commission))
运行程序:
在这里插入图片描述

3.6挑战: 圆的面积

3.6.1 介绍

我们通过实验已经学习了基本的 Python 3 语法。现在我们就来用一个挑战来巩固一下我们的实验效果。
本挑战中,我们将实现一个程序用来计算半径为 2 的圆的面积并打印输出。

3.6.2 目标

在下创建一个 Python 脚本 并用vim编辑:/home/wiseinsight/CircleArea.py
sudo vim CircleArea.py
CircleArea.py 能够计算出一个半径为2的圆的面积,并且把面积打印出来,保留小数点后10位。
不要使用 input 等方法获得输入,程序不需要输入任何参数,程序执行如下,直接输出半径为 2 的圆的面积:
$ python3 CircleArea.py

3.6.3 提示语

• import math
• 使用 可以控制输出的小数位数,可以使用 来进行格式化输出保留 10 位小数format’{:.10f}'.format()
• 请不要使用 input 获取输入,程序执行不需要任何输入的参数
知识点
• 导入模块
• 打印输出
• 运算符和表达式

3.6.4 参考代码

注意:请务必先独立思考获得 PASS 之后再查看参考代码,直接拷贝代码收获不大
CircleArea.py参考代码:
#!/usr/bin/env python3
import math
计算圆的面积
area = 2 * 2 * math.pi
格式化输出圆的面积,保留10位小数
print(“{:.10f}”.format(area))
在这里插入图片描述

3.7总结

本节实验知识点回顾:
• 关系/逻辑运算
• 表达式
• 类型转换
除了数值运算,关系和逻辑运算也是程序的重要组成部分。另外 Python 是强类型语言,所以必要的时候需要手动进行类型转换。

4.1实验介绍

我们处理现实生活中的问题时会做出决定,就像决定买哪种相机或者怎样更好的打篮球。
同样我们写计算机程序的时候也要做相同的事情。
我们通过 , 语句来做决定,我们使用它来改变程序运行的流程。ifelse

4.1.1 知识点

• 如果 语句
• else 语句
• 真值检测

4.2如果 语句

语法如下:
if expression:
do this
如果表达式 的值为真(不为零的任何值都为真),程序将执行缩进后的内容。务必要使用正确的缩进,在表达式为真的情况将会执行缩进的所有行。expression
一个简单的例子,使用写入文件 ,程序接受用户输入的一个数并且检查这个数是否小于 100。vim/home/wiseinsight/number100.py
非root用户,vim前要加,chmod也是。sudo
#!/usr/bin/env python3
number = int(input("Enter a number: "))
if number < 100:
print(“The number is less than 100”)
然后我们运行它:
sudo chmod +x number100.py
./number100.py
在这里插入图片描述

4.3Else 语句

在上面的例子中,我们想要这样做:如果输入数大于 100 则打印 “Greater than”。我们使用 语句来做到这一点,它将在 语句未满足的情况时工作。elseif
#!/usr/bin/env python3
number = int(input("Enter a number: "))
if number < 100:
print(“The number is less than 100”)
else:
print(“The number is greater than 100”)
运行它:
在这里插入图片描述

另一个非常基础的例子:
x = int(input("Please enter an integer: "))
if x < 0:
x = 0
print(‘Negative changed to zero’)
elif x == 0:
print(‘Zero’)
elif x == 1:
print(‘Single’)
else:
print(‘More’)
在这里插入图片描述

在上面的例子中, 是 的缩写。elifelse if

4.4真值检测

检测真值的优雅方式是这样的:
if x:
pass
不要像下面这样做:
if x == True:
pass

4.5总结

这个实验非常简单,这里只是提一句,Python 中的很多值是具有布尔意义的,所以有时候我们可以写的更优雅一点。
同时也要注意下 的基本语法结构。ifelifelse

5.1实验介绍

在以前的例子里,有些时候我们需要多次执行相同的任务,我们使用一个计数器来检查代码需要执行的次数。这个技术被称为循环。

5.1.1 实验知识点

• 而 循环
• print() 函数的 end 参数
• 列表
• 索引
• 切片
• for 循环
• range() 函数
• 继续 关键字
• for 循环中的 else 关键字

5.2while 循环

while语句的语法如下:
while condition:
statement1
statement2
想要多次执行的代码必须以正确的缩进放在 语句下面。在表达式condition为真的时候它们才会执行。同if-else一样,非零值为真。启动python3交互页面,让我们写一个简单的代码,它按顺序打印 0 到 10 的数字:while

n = 0
while n < 11:
… print(n)
… n += 1

在这里插入图片描述

在第一行我们使 ,然后在 语句中把条件设置为 ,这意味着在 语句下面缩进的所有行将会被执行,直到 的值大于等于11。在循环里我们只是打印 n 的值然后令它增一。n = 0whilen < 11whilen
想想如果没有循环语句,你想要打印 0 到 10 的所有数字,那你得手动打印 11 次!

5.2.1 斐波那契(斐波那契)数列

让我们来试试打印斐波那契数列。这个数列前两项为 1,之后的每一个项都是前两项之和。所以这个数列看起来就像这样:1,1,2,3,5,8,13 …
#!/usr/bin/env python3
a, b = 0, 1
while b < 100:
print(b)
a, b = b, a + b
运行程序:
在这里插入图片描述

第一行代码中我们初始化 和 。当 的值小于 100 的时候,循环执行代码。循环里我们首先打印 的值,然后在下一行将 的值赋值给 , 的值赋值给 。abbba + bbba
学习其他语言的同学在这里可能有些困惑,你可以这样理解,Python 中赋值语句执行时会先对赋值运算符右边的表达式求值,然后将这个值赋值给左边的变量。
默认情况下, 除了打印你提供的字符串之外,还会打印一个换行符,所以每调用一次 就会换一次行,如同上面一样。print()print()
你可以通过 的另一个参数 来替换这个换行符,就像下面这样,下面的程序写入 :print()endfibonacci2.py
#!/usr/bin/env python3
a, b = 0, 1
while b < 100:
print(b, end=’ ')
a, b = b, a + b
print()
运行程序:
在这里插入图片描述

5.2.2 幂级数

我们来写一个程序计算幂级数:e^x = 1 + x + x^2 / 2! + x^3 / 3! + … + x^n / n! (0 < x < 1)。
该程序写入代码文件powerseries.py
#!/usr/bin/env python3
x = float(input("Enter the value of x: "))
n = term = num = 1
result = 1.0
while n <= 100:
term *= x / n
result += term
n += 1
if term < 0.0001:
break
print(“No of Times= {} and Sum= {}”.format(n, result))
运行程序:
在这里插入图片描述

在这个程序里我们介绍一个新的关键字 ,它可以终止最里面的循环。这个例子里我们在 语句里使用 :breakifbreak
if term < 0.0001:
break
这意味着如果 term的值小于0.0001 ,那么终止循环。

5.2.3 乘法表

这个例子里我们打印 10 以内的乘法表。写入代码文件/home/wiseinsight/multiplication.py
#!/usr/bin/env python3
i = 1
print(“-” * 50)
while i < 11:
n = 1
while n <= 10:
print(“{:5d}”.format(i * n), end=‘’)
n += 1
print()
i += 1
print(“-” * 50)
运行如下:
在这里插入图片描述

这里我们在 循环里使用了另一个 循环,这被称为嵌套循环。你应该已经看到一条有趣的语句:whilewhile
print(“-” * 50)
字符串若是乘上整数 n,将返回由 n 个此字符串拼接起来的新字符串。
下面是一些例子:

‘s’ * 10
‘ssssssssss’
print(“*” * 10)


print(“#” * 10)
####################
print(“–” * 10)


print(“-” * 20)


在这里插入图片描述

5.2.4 一些打印星号的例子

这里是一些你可以在大学的实验报告里经常看到的例子。

5.2.4.1. 设计 1

!/usr/bin/env python3
row = int(input("Enter the number of rows: "))
n = row
while n >= 0:
x = “*” * n
print(x)
n -= 1
运行这个程序:
在这里插入图片描述

5.2.4.2. 设计 2

!/usr/bin/env python3
n = int(input(“Enter the number of rows: “))
i = 1
while i <= n:
print(”*” * i)
i += 1
运行这个程序:
在这里插入图片描述

5.2.4.3 设计 3

!/usr/bin/env python3
row = int(input("Enter the number of rows: "))
n = row
while n >= 0:
x = “*” * n
y = " " * (row - n)
print(y + x)
n -= 1
运行这个程序:
在这里插入图片描述

5.3列表

在继续学习循环之前,我们先学习一个叫做列表的数据结构。它可以写作中括号之间的一列逗号分隔的值。列表的元素不必是同一类型:

a = [ 1, 342, 223, ‘India’, ‘Fedora’]
a
[1, 342, 223, ‘India’, ‘Fedora’]
在这里插入图片描述

你可以将上面的列表想象为一堆有序的盒子,盒子包含有上面提到的值,每个盒子都有自己的编号(红色的数字),编号从零开始,你可以通过编号访问每一个盒子里面的值。对于列表,这里的编号称为索引。
在这里插入图片描述

我们像下面这样通过索引来访问列表中的每一个值:

a[0]
1
a[4]
‘Fedora’
如果我们使用负数的索引,那将会从列表的末尾开始计数,像下面这样:
a[-1]
‘Fedora’
你甚至可以把它切成不同的部分,这个操作称为切片,例子在下面给出:
a[0:-1]
[1, 342, 223, ‘India’]
a[2:-2]
[223]
切片并不会改变正在操作的列表,切片操作返回其子列表,这意味着下面的切片操作返回列表一个新的(栈)拷贝副本:
a[:]
[1, 342, 223, ‘India’, ‘Fedora’]
切片的索引有非常有用的默认值;省略的第一个索引默认为零,省略的第二个索引默认为切片的字符串的大小:
a[:-2]
[1, 342, 223]
a[-2:]
[‘India’, ‘Fedora’]
有个办法可以很容易地记住切片的工作方式:切片时的索引是在两个元素之间 。左边第一个元素的索引为 0,而长度为 n 的列表其最后一个元素的右界索引为 n。例如:
±–±----±----±--------±---------+
| 1 | 342 | 223 | ‘India’ | ‘Fedora’ |
±–±----±----±--------±---------+
0 1 2 3 4 5
-5 -4 -3 -2 -1
上面的第一行数字给出列表中的索引点 0…5。第二行给出相应的负索引。切片是从 i 到 j 两个数值表示的边界之间的所有元素。
对于非负索引,如果上下都在边界内,切片长度就是两个索引之差。例如 是 2。a[2:4]
Python 中有关下标的集合都满足左闭右开原则,切片中也是如此,也就是说集合左边界值能取到,右边界值不能取到。
对上面的列表, 用数学表达式可以写为 ,其索引取值为 ,所以能将中所有值获取到。你也可以用, 效果是一样的。a[0:5][0,5)0,1,2,3,4aa[:5]
而,因为左闭右开原则,其取值为 是不包含 的。a[-5:-1]-5,-4,-3,-2-1
为了取到最后一个值,你可以使用 ,它代表了取该列表最后5个值。a[-5:]
试图使用太大的索引会导致错误:
a[32]
Traceback (most recent call last):
File “”, line 1, in
IndexError: list index out of range
a[-10]
Traceback (most recent call last):
File “”, line 1, in
IndexError: list index out of range
Python 能够优雅地处理那些没有意义的切片索引:一个过大的索引值(即大于列表实际长度)将被列表实际长度所代替,当上边界比下边界大时(即切片左值大于右值)就返回空列表:
a[2:32]
[223, ‘India’, ‘Fedora’]
a[32:]
[]
切片操作还可以设置步长,就像下面这样:
a[1::2]
[342, ‘India’]
它的意思是,从切片索引 1 到列表末尾,每隔两个元素取值。
列表也支持连接这样的操作,它返回一个新的列表:
a + [36, 49, 64, 81, 100]
[1, 342, 223, ‘India’, ‘Fedora’, 36, 49, 64, 81, 100]
列表允许修改元素:
cubes = [1, 8, 27, 65, 125]
cubes[3] = 64
cubes
[1, 8, 27, 64, 125]
也可以对切片赋值,此操作可以改变列表的尺寸,或清空它:
letters = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’]
letters
[‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’]
#替换某些值
letters[2:5] = [‘C’, ‘D’, ‘E’]
letters
[‘a’, ‘b’, ‘C’, ‘D’, ‘E’, ‘f’, ‘g’]
现在移除他们
letters[2:5] = []
letters
[‘a’, ‘b’, ‘f’, ‘g’]
#通过替换所有元素为空列表来清空这个列表
letters[:] = []
letters
[]
细心的同学可能发问了,前面不是说过切片操作不改变列表么?严格来说,这里并不算真正的切片操作,只是上面代码中赋值运算符左边的这种操作与切片操作形式一样而已。
要检查某个值是否存在于列表中,你可以这样做:
a = [‘wiseinsight’, ‘is’, ‘cool’]
‘cool’ in a
True
‘Linux’ in a
False
这意味着我们可以将上面的语句使用在 子句中的表达式。通过内建函数 我们可以获得列表的长度:iflen()
len(a)
3
如果你想要检查列表是否为空,请这样做:
if list_name: # 列表不为空
pass
else: # 列表为空
pass
列表是允许嵌套的(创建一个包含其它列表的列表),例如:
a = [‘a’, ‘b’, ‘c’]
n = [1, 2, 3]
x = [a, n]
x
[[‘a’, ‘b’, ‘c’], [1, 2, 3]]
x[0]
[‘a’, ‘b’, ‘c’]
x[0][1]
‘b’

5.4for 循环

通过 语句我们可以使用 for 循环。Python 里的 for 循环与 C 语言中的不同。这里的 for 循环遍历任何序列(比如列表和字符串)中的每一个元素。下面给出示例:for

a = [‘wiseinsight’, ‘is’, ‘powerful’]
for x in a:
… print(x)

wiseinsight
is
powerful
我们也能这样做:
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for x in a[::2]:
… print(x)
1
3
5
7
9

5.4.1 range() 函数

如果你需要一个数值序列,内置函数range()会很方便,它生成一个等差数列(并不是列表):

for i in range(5):
… print(i)

0
1
2
3
4
range(1, 5)
range(1, 5)
list(range(1, 5))
[1, 2, 3, 4]
list(range(1, 15, 3))
[1, 4, 7, 10, 13]
list(range(4, 15, 2))
[4, 6, 8, 10, 12, 14]

5.5连续 语句

如同 ,我们可以在循环中使用另一个语句 。它会跳过其后的代码回到循环开始处执行。这意味着它可以帮助你跳过部分循环。在下面的例子中,我们要求用户输入一个整数,如果输入的是负数,那么我们会再次要求输入,如果输入的是整数,我们计算这个数的平方。用户输入 0 来跳出这个无限循环。breakcontinue
#!/usr/bin/env python3
while True:
n = int(input("Please enter an Integer: "))
if n < 0:
continue # 这会返回到循环开始处执行
elif n == 0:
break
print("Square is ", n ** 2)
print(“Goodbye”)
运行程序:
在这里插入图片描述

5.6循环的 else 语句

我们可以在循环后面使用可选的 语句。它将会在循环完毕后执行,除非有 语句终止了循环。elsebreak

for i in range(0, 5):
… print(i)
… else:
… print(“Bye bye”)

0
1
2
3
4
Bye bye
在本课程的后续内容中,我们会看到更多有关 和 的例子。breakcontinue

5.7棍子游戏

这是一个非常简单的游戏。这里有 21 根棍子,首先用户选 1 到 4 根棍子,然后电脑选 1到 4 根棍子。谁选到最后一根棍子谁就输。判断一下用户有赢的机会吗?如果没有的话,如何修改游戏规则可以使用户有赢的机会呢?
特别说明:用户和电脑一次选的棍子总数只能是5。
#!/usr/bin/env python3
sticks = 21
print(“There are 21 sticks, you can take 1-4 number of sticks at a time.”)
print(“Whoever will take the last stick will loose”)
while True:
print("Sticks left: " , sticks)
sticks_taken = int(input(“Take sticks(1-4):”))
if sticks == 1:
print(“You took the last stick, you loose”)
break
if sticks_taken >= 5 or sticks_taken <= 0:
print(“Wrong choice”)
continue
print("Computer took: " , (5 - sticks_taken) , “\n”)
sticks -= 5

5.8总结

这个实验中我们了解了两种循环: 和 循环,其中的 循环我们通常与 函数配合使用,要特别注意的是, 函数返回的并不是列表而是一种可迭代对象:whileforforrange()range()

python 中 循环的 forelse子句给我们提供了检测循环是否顺利执行完毕的一种优雅方法。

6.1实验介绍

Python 有许多内建的数据结构。如果你困惑于什么是数据结构,那么可以参考一下维基百科。
简单的来说,数据结构(data structure)是计算机中存储、组织数据的方式。比如我们之前的课程中使用过的列表就是一种数据结构,在这里我们还会深入学习它。

6.1.1 知识点

• 列表的方法与列表元素的删除
• 将列表用作栈和队列
• 列表推导式
• 元组、集合、字典的创建与操作
• enumerate()和 函数zip()

6.2列表

a = [23, 45, 1, -3434, 43624356, 234]
a.append(45)
a
[23, 45, 1, -3434, 43624356, 234, 45]
首先我们建立了一个列表 。然后调用列表的方法 添加元素 到列表末尾。你可以看到元素 45 已经添加到列表的末端了。有些时候我们需要将数据插入到列表的任何位置,这时我们可以使用列表的 方法。aa.append(45)45insert()
a.insert(0, 1) # 在列表索引 0 位置添加元素 1
a
[1, 23, 45, 1, -3434, 43624356, 234, 45]
a.insert(0, 111) # 在列表索引 0 位置添加元素 111
a
[111, 1, 23, 45, 1, -3434, 43624356, 234, 45]
列表方法 会返回列表元素中 的数量。我们来检查一下 这个元素在列表中出现了多少次。count(s)s45
a.count(45)
2
如果你想要在列表中移除任意指定值,你需要使用 方法。remove()
a.remove(234)
a
[111, 1, 23, 45, 1, -3434, 43624356, 45]
现在我们反转整个列表。
a.reverse()
a
[45, 43624356, -3434, 1, 45, 23, 1, 111]
怎样将一个列表的所有元素添加到另一个列表的末尾呢,可以使用列表的 方法。extend()
b = [45, 56, 90]
a.extend(b) # 添加 b 的元素而不是 b 本身
a
[45, 43624356, -3434, 1, 45, 23, 1, 111, 45, 56, 90]
给列表排序,我们使用列表的 方法,排序的前提是列表的元素是可比较的。sort()
a.sort()
a
[-3434, 1, 1, 23, 45, 45, 45, 56, 90, 111, 43624356]
你也能使用 关键字删除指定位置的列表元素。del
del a[-1]
a
[-3434, 1, 1, 23, 45, 45, 45, 56, 90, 111]
在这里插入图片描述

6.2.1 将列表用作栈和队列

栈是我们通常所说的一种LIFO (Last In First Out 后进先出)数据结构。它的意思是最后进入的数据第一个出来。一个最简单的例子往一端封闭的管道放入一些弹珠然后取出来,如果你想把弹珠取出来,你必须从你最后放入弹珠的位置挨个拿出来。用代码实现此原理:

a = [1, 2, 3, 4, 5, 6]
a
[1, 2, 3, 4, 5, 6]
a.pop()
6
a.pop()
5
a.pop()
4
a.pop()
3
a
[1, 2]
a.append(34)
a
[1, 2, 34]
上面的代码中我们使用了一个新方法 。传入一个参数 i 即 会将第 i 个元素弹出。pop()pop(i)
在我们的日常生活中会经常遇到队列,比如售票窗口、图书馆、超市的结账出口。队列是一种在末尾追加数据以及在开始弹出数据的数据结构。与栈不同,它是FIFO (First in First Out 先进先出)的数据结构。
a = [1, 2, 3, 4, 5]
a.append(1)
a
[1, 2, 3, 4, 5, 1]
a.pop(0)
1
a.pop(0)
2
a
[3, 4, 5, 1]
我们使用 弹出列表中第一个元素。a.pop(0)
在这里插入图片描述

6.2.2 列表推导式

列表推导式为从序列中创建列表提供了一个简单的方法。如果没有列表推导式,一般都是这样创建列表的:通过将一些操作应用于序列的每个成员并通过返回的元素创建列表,或者通过满足特定条件的元素创建子序列。
假设我们创建一个 squares 列表,可以像下面这样创建。

squares = []
for x in range(10):
… squares.append(x2)

squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
注意这个 for 循环中的被创建(或被重写)的名为 的变量在循环完毕后依然存在。使用如下方法,我们可以计算平方 的值而不会产生任何的副作用:。x
squares = list(map(lambda x: x
2, range(10)))
等价于下面的列表推导式。
squares = [x**2 for x in range(10)]
上面这个方法更加简明且易读。
列表推导式由包含一个表达式的中括号组成,表达式后面跟随一个 for 子句,之后可以有零或多个 for 或 if 子句。结果是一个列表,由表达式依据其后面的 for 和 如果 子句上下文计算而来的结果构成。
例如,如下的列表推导式结合两个列表的元素,如果元素之间不相等的话:
[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
等同于:
combs = []
for x in [1,2,3]:
… for y in [3,1,4]:
… if x != y:
… combs.append((x, y))

combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
值得注意的是在上面两个方法中的 for 和 if 语句的顺序。
列表推导式也可以嵌套。
a=[1,2,3]
z = [x + 1 for x in [x ** 2 for x in a]]
z
[2, 5, 10]

6.3元组

元组是由数个逗号分割的值组成。

a = ‘Fedora’, ‘wiseinsight’, ‘Kubuntu’, ‘Pardus’
a
(‘Fedora’, ‘wiseinsight’, ‘Kubuntu’, ‘Pardus’)
a[1]
‘wiseinsight’
for x in a:
… print(x, end=’ ')

Fedora wiseinsight Kubuntu Pardus
你可以对任何一个元组执行拆封操作并赋值给多个变量,就像下面这样:
divmod(15,2)
(7, 1)
x, y = divmod(15,2)
x
7
y
1
元组是不可变类型,这意味着你不能在元组内删除或添加或编辑任何值。如果你尝试这些操作,将会出错:
a = (1, 2, 3, 4)
del a[0]
Traceback (most recent call last):
File “”, line 1, in
TypeError: ‘tuple’ object doesn’t support item deletion
要创建只含有一个元素的元组,在值后面跟一个逗号。
a = (123)
a
123
type(a)
<class ‘int’>
a = (123, )
b = 321,
a
(123,)
b
(321,)
type(a)
<class ‘tuple’>
type(b)
<class ‘tuple’>
通过内建函数 你可以知道任意变量的数据类型。还记得我们使用 函数来查询任意序列类型数据的长度吗?type()len()
type(len)
<class ‘builtin_function_or_method’>

6.4集合

集合是一个无序不重复元素的集。基本功能包括关系测试和消除重复元素。集合对象还支持 union(联合),intersection(交),difference(差)和 symmetric difference(对称差集)等数学运算。
大括号或 set() 函数可以用来创建集合。注意:想要创建空集合,你必须使用 set() 而不是 {}。后者用于创建空字典,我们在下一节中介绍的一种数据结构。
下面是集合的常见操作:

basket = {‘apple’, ‘orange’, ‘apple’, ‘pear’, ‘orange’, ‘banana’}
print(basket) # 你可以看到重复的元素被去除
{‘orange’, ‘banana’, ‘pear’, ‘apple’}
‘orange’ in basket
True
‘crabgrass’ in basket
False

#演示对两个单词中的字母进行集合操作

a = set(‘abracadabra’)
b = set(‘alacazam’)
a # a 去重后的字母
{‘a’, ‘r’, ‘b’, ‘c’, ‘d’}
a - b # a 有而 b 没有的字母
{‘r’, ‘d’, ‘b’}
a | b # 存在于 a 或 b 的字母
{‘a’, ‘c’, ‘r’, ‘d’, ‘b’, ‘m’, ‘z’, ‘l’}
a & b # a 和 b 都有的字母
{‘a’, ‘c’}
a ^ b # 存在于 a 或 b 但不同时存在的字母
{‘r’, ‘d’, ‘b’, ‘m’, ‘z’, ‘l’}
在这里插入图片描述

从集合中添加或弹出元素:

a = {‘a’,‘e’,‘h’,‘g’}
a.pop() # 随机移除一个元素
‘h’
a.add(‘c’)
a
{‘c’, ‘e’, ‘g’, ‘a’}

6.5字典

字典是是无序的键值对()集合,同一个字典内的键必须是互不相同的。一对大括号 创建一个空字典。初始化字典时,在大括号内放置一组逗号分隔的键:值对,这也是字典输出的方式。我们使用键来检索存储在字典中的数据。key:value{}

data = {‘kushal’:‘Fedora’, ‘kart_’:‘Debian’, ‘Jace’:‘Mac’}
data
{‘kushal’: ‘Fedora’, ‘Jace’: ‘Mac’, ‘kart_’: ‘Debian’}
data[‘kart_’]
‘Debian’
创建新的键值对很简单:
data[‘parthan’] = ‘Ubuntu’
data
{‘kushal’: ‘Fedora’, ‘Jace’: ‘Mac’, ‘kart_’: ‘Debian’, ‘parthan’: ‘Ubuntu’}
使用 关键字删除任意指定的键值对:del
del data[‘kushal’]
data
{‘Jace’: ‘Mac’, ‘kart_’: ‘Debian’, ‘parthan’: ‘Ubuntu’
使用 关键字查询指定的键是否存在于字典中。in
‘wiseinsight’ in data
False
必须知道的是,字典中的键必须是不可变类型,比如你不能使用列表作为键。
dict()可以从包含键值对的元组中创建字典。
dict(((‘Indian’,‘Delhi’),(‘Bangladesh’,‘Dhaka’)))
{‘Indian’: ‘Delhi’, ‘Bangladesh’: ‘Dhaka’}
如果你想要遍历一个字典,使用字典的 方法。items()
data
{‘kart_’: ‘Debian’, ‘Jace’: ‘Mac’, ‘parthan’: ‘Ubuntu’}
for x, y in data.items():
… print(“{} uses {}”.format(x, y))

kart_ uses Debian
Jace uses Mac
parthan uses Ubuntu
在这里插入图片描述

许多时候我们需要往字典中的元素添加数据,我们首先要判断这个元素是否存在,不存在则创建一个默认值。如果在循环里执行这个操作,每次迭代都需要判断一次,降低程序性能。
我们可以使用 更有效率的完成这个事情。dict.setdefault(key, default)

data = {}
data.setdefault(‘names’, []).append(‘Ruby’)
data
{‘names’: [‘Ruby’]}
data.setdefault(‘names’, []).append(‘Python’)
data
{‘names’: [‘Ruby’, ‘Python’]}
data.setdefault(‘names’, []).append(‘C’)
data
{‘names’: [‘Ruby’, ‘Python’, ‘C’]}
试图索引一个不存在的键将会抛出一个keyError错误。我们可以使用 来索引键,如果键不存在,那么返回指定的 default 值。dict.get(key, default)
data[‘foo’]
Traceback (most recent call last):
File “”, line 1, in
KeyError: ‘foo’
data.get(‘foo’, 0)
0
如果你想要在遍历列表(或任何序列类型)的同时获得元素索引值,你可以使用 。enumerate()
for i, j in enumerate([‘a’, ‘b’, ‘c’]):
… print(i, j)

0 a
1 b
2 c
你也许需要同时遍历两个序列类型,你可以使用 函数。zip()
a = [‘Pradeepto’, ‘Kushal’]
b = [‘OpenSUSE’, ‘Fedora’]
for x, y in zip(a, b):
… print(“{} uses {}”.format(x, y))

Pradeepto uses OpenSUSE
Kushal uses Fedora
在这里插入图片描述

在这里插入图片描述

**

6.6程序示例

**

本节实验将会通过两个实例程序来熟悉 Python3 的基本数据结构:

  1. 判断学生成绩是否达标的程序
  2. 计算两个矩阵的 Hadamard 乘积

6.6.1 students.py

这是一个判断学生成绩是否达标的程序,要求输入学生数量,以及各个学生物理、数学、历史三科的成绩,如果总成绩小于 120,程序打印 “failed”,否则打印 “passed”。
代码写入 文件:/home/wiseinsight/students.py
#!/usr/bin/env python3
n = int(input(“Enter the number of students: “))
data = {} # 用来存储数据的字典变量
Subjects = (‘Physics’, ‘Maths’, ‘History’) # 所有科目
for i in range(0, n):
name = input('Enter the name of the student {}: '.format(i + 1)) # 获得学生名称
marks = []
for x in Subjects:
marks.append(int(input('Enter marks of {}: '.format(x)))) # 获得每一科的分数
data[name] = marks
for x, y in data.items():
total = sum(y)
print(”{}'s total marks {}”.format(x, total))
if total < 120:
print(x, “failed 😦”)
else:
print(x, “passed 😃”)
name 和 marks 是变量,name 用来存储学生的名称,marks 是个列表,用来存储输入的学生的成绩数据。
data 是个字典,字典的键值对中,键指的是 name 的值,值指的是 marks 的值。因此会使用 将屏蔽的关键字存入到 data 字典。data[name] = marks
最后通过 for 循环遍历字典,x 为学生的 name,y 为学生成绩列表 markd, 函数会将传入的列表进行加和。sum()
运行如下:
在这里插入图片描述

6.6.2 matrixmul.py

这个例子里我们计算两个矩阵的 Hadamard 乘积。要求输入矩阵的行/列数(在这里假设我们使用的是 n × n 的矩阵)。
代码写入 文件:/home/wiseinsight/matrixmul.py
#!/usr/bin/env python3
n = int(input(“Enter the value of n: “))
print(“Enter values for the Matrix A”)
a = []
for i in range(n):
a.append([int(x) for x in input().split()])
print(“Enter values for the Matrix B”)
b = []
for i in range(n):
b.append([int(x) for x in input().split()])
c = []
for i in range(n):
c.append([a[i][j] * b[i][j] for j in range(n)])
print(“After matrix multiplication”)
print(”-” * 7 * n)
for x in c:
for y in x:
print(str(y).rjust(5), end=’ ')
print()
print(“-” * 7 * n)
运行如下:
在这里插入图片描述

这里我们使用了几次列表推导式。首先通过 获得用户输入的字符串,再使用 分割字符串得到一系列的数字字符串,然后用 从每个数字字符串创建对应的整数值。我们也使用了 来得到矩阵乘积的每一行数据。[int(x) for x in input().split()]input()split()int()[a[i][j] * b[i][j] for j in range(n)]

6.7总结

本实验了解了 Python 内置的几种常用数据结构,在写程序的过程中,不同的场景应当选取合适的数据结构。
一般来说,目前我们见到的数据结构已经够用了,不过 Python 中还有一些其它有用的数据结构,可以在这里了解:https://docs.python.org/3/library/datatypes.html。

7.1实验介绍

字符串是 Python 中最常用的数据类型。本节实验将会学习如何对 Python3 的字符串进行处理操作。

7.1.1 知识点

• 字符串的3种表示
• 字符串的分割、连接、大小写转换、搜索等常用操作

7.2字符串表示

可以通过几种不同的方式表示字符串。如单引号()或双引号()。下面的例子能帮助你更好的理解字符串。‘…’“…”

s = “I am Chinese”
s
‘I am Chinese’
s = “Here is a line
… split in two lines”
s
‘Here is a line split in two lines’
s = “Here is a line \n split in two lines”
s
‘Here is a line \n split in two lines’
print(s)
Here is a line
split in two lines
如果你想要分几行输入字符串,并且希望行尾的换行符自动包含到字符串当中,可以使用三对引号: 或 。“”“…”“”‘’‘…’‘’
print(“”"
… Usage: thingy [OPTIONS]
… -h Display this usage message
… -H hostname Hostname to connect to
… “”")
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to

在这里插入图片描述

7.3字符串的方法

每一个字符串对象都有几个可用的内建方法,我们已经使用过一些了,比如 。s.split()

s = “wiseinsight is good”
s.title()
‘Wiseinsight Is Good’
方法 返回字符串的标题版本,即单词首字母大写其余字母小写。title()
z = s.upper()
z
‘WISEINSIGHT IS GOOD’
z.lower()
‘wiseinsight is good’
方法 返回字符串全部大写的版本,反之 返回字符串的全部小写版本。upper()lower()
s = “I am A pRoGraMMer”
s.swapcase()
‘i AM a PrOgRAmmER’
方法 返回字符串大小写交换后的版本 :)swapcase()
s = “jdwb 2323bjb”
s.isalnum()
False
s = “jdwb2323bjb”
s.isalnum()
True
方法 检查所有字符是否只有字母和数字,上面的代码中第一行的字符串 中包含空格字符,所以返回 。isalnum()sFalse
s = “SankarshanSir”
s.isalpha()
True
s = “Sankarshan Sir”
s.isalpha()
False
方法 检查字符串之中是否只有字母。isalpha()
s = “1234”
s.isdigit() # 检查字符串是否所有字符为数字
True
s = “Wiseinsight is coming”
s.islower() # 检查字符串是否所有字符为小写
False
s = “Wiseinsight Is Coming”
s.istitle() # To 检查字符串是否为标题样式
True
s = “CHINA”
s.isupper() # 检查字符串是否所有字符为大写
True
我们可以使用 分割任意字符串, 允许有一个参数,用来指定字符串以什么字符分隔(默认为 ),它返回一个包含所有分割后的字符串的列表。split()split()" "
s = “We all love Python”
s.split()
[‘We’, ‘all’, ‘love’, ‘Python’]
x = “wiseinsight:is:waiting”
x.split(‘:’)
[‘wiseinsight’, ‘is’, ‘waiting’]
相反的,方法 使用指定字符连接多个字符串,它需要一个包含字符串元素的列表作为输入然后连接列表内的字符串元素。join()
“-”.join(“GNU/Linux is great”.split())
‘GNU/Linux-is-great’
在上面的例子中,我们基于空格 分割字符串 ,然后用 连接它们。" ““GNU/Linux is great””-"
在这里插入图片描述
在这里插入图片描述

7.4字符串剥离

字符串有几个进行剥离操作的方法。最简单的一个是 ,用来剥离字符串首尾中指定的字符,它允许有一个字符串参数,这个参数为剥离哪些字符提供依据。不指定参数则默认剥离掉首尾的空格和换行符,代码如下:strip(chars)

s = " a bc\n "
s.strip()
‘a bc’
你可以使用 或 只对字符串左或右剥离。lstrip(chars)rstrip(chars)
s = “www.foss.in”
s.lstrip(“cwsd.”) #删除在字符串左边出现的’c’,‘w’,‘s’,‘d’,‘.‘字符
‘foss.in’
s.rstrip(“cnwdi.”) #删除在字符串右边出现的’c’,‘n’,‘w’,‘d’,‘i’,’.'字符
‘www.foss’

7.5文本搜索

字符串有一些方法能够帮助你搜索字符串里的文本或子字符串。下面给出示例:

s = “faulty for a reason”
s.find(“for”)
7
s.find(“fora”)
-1
s.startswith(“fa”) # 检查字符串是否以 fa 开头
True
s.endswith(“reason”) # 检查字符串是否以 reason 结尾
True
find()能帮助你找到第一个匹配的子字符串,没有找到则返回 -1。
在这里插入图片描述

7.6回文检查

回文是一种无论从左还是从右读都一样的字符序列。比如"夫人"。在这个例子中,我们检查用户输入的字符串是否是回文,并输出结果。
代码写入文件 :/home/wiseinsight/palindrome.py
#!/usr/bin/env python3
s = input("Please enter a string: ")
z = s[::-1] #把输入的字符串s 进行倒序处理形成新的字符串z
if s == z:
print(“The string is a palindrome”)
else:
print(“The string is not a palindrome”)
运行程序:
在这里插入图片描述

7.7单词计数

在讲解单词计数之前我们先了解一个概念:格式化操作符(%)。
我们先看下面的这个例子:
print(“my name is %s.I am %d years old” % (‘wiseinsight’,4))
在这里插入图片描述

在这个例子中, 为第一个格式符,表示一个字符串; 为第二个格式符,表示一个整数。格式符为真实值预留位置,并控制显示的格式。常用的有:%s%d
%s 字符串(用 str() 函数进行字符串转换)
%r 字符串(用 repr() 函数进行字符串转换)
%d 十进制整数
%f 浮点数
%% 字符"%"
那么接下来我们对用户输入的一行文本进行单词计数。
代码写入文件 :/home/wiseinsight/countwords.py
#!/usr/bin/env python3
s = input("Enter a line: “)
print(“The number of words in the line are %d” % (len(s.split(” "))))
运行程序:
在这里插入图片描述

7.8总结

回顾本节实验的知识点:
• 字符串的3种表示
• 字符串的分割、连接、大小写转换、搜索等常用操作
本实验学习了字符串的几种表示方法(3种引号)以及对字符串的各种常用操作(分割、连接、大小写转换、搜索…),应当熟练掌握它们。

8.1实验介绍

我们经常需要在同一个程序里多次复用代码。函数可以很好的帮助我们完成这一点。我们在函数里写我们要重复做的事,然后我们在任何需要的时候调用它。我们已经看到一些内建的函数,比如 ,。len()divmod()

8.1.1 知识点

• 函数的定义
• 局部/全局变量的概念
• 默认参数,关键字参数及强制关键字参数
• 文档字符串的使用
• 高阶函数,map() 函数

8.2定义一个函数

我们使用关键字 来定义一个函数,语法描述如下所示:def
def 函数名(参数):
语句1
语句2
让我们编写一个函数,它将接受两个整数作为输入,然后返回总和。

def mysum(a, b):
… return a + b
第二行有个 关键字,我们把 的值返回给调用者。returna + b
你必须像下面这样调用这个函数。
res = mysum(234234, 34453546464)
res
34453780698
在这里插入图片描述

还记得我们上一个实验讲过的回文检查程序么,让我们编写一个函数来检查给出的字符串是否为回文,然后返回 或者 。TrueFalse
#!/usr/bin/env python3
def palindrome(s):
return s == s[::-1]
if name == ‘main’:
s = input("Enter a string: ")
if palindrome(s):
print(“Yay a palindrome”)
else:
print(“Oh no, not a palindrome”)
将上述代码写入到 testpalindrome.py 文件,执行如下:
在这里插入图片描述

8.3局域或全局变量

我们通过几个例子来弄明白局域或全局变量,首先我们在函数内部和函数调用的代码中都使用同一个变量 a,将下方代码写入 :/home/wiseinsight/local.py
#!/usr/bin/env python3
def change():
a = 90
print(a)
a = 9
print("Before the function call ", a)
print(“inside change function”, end=’ ')
change()
print("After the function call ", a)
运行程序:
在这里插入图片描述

首先我们对 赋值 9,然后调用更改函数,这个函数里我们对 赋值 90,然后打印 的值。调用函数后我们再次打印 的值。aaaa
当我们在函数里写 时,它实际上创建了一个新的名为 的局部变量,这个变量只在函数里可用,并且会在函数完成时销毁。所以即使这两个变量的名字都相同,但事实上他们并不是同一个变量。a = 90a
那么如果我们先定义 ,在函数中是否可以直接使用呢?a
例如下面这段代码:
a = 9
def change():
print(a)
change()
这段代码是没有问题的,可以直接打印输出 9。稍微改动一下:
a = 9
def change():
print(a)
a = 100
change()
在这里插入图片描述

现在就会报错了:“UnboundLocalError: local variable ‘a’ referenced before assignment”,原因是当函数中只要用到了变量 a,并且 a 出现在表达式等于号的前面,就会被当作局部变量。当执行到 的时候会报错,因为 a 作为函数局部变量是在 之后才定义的。print(a)print(a)
现在我们使用 关键字,对函数中的 标志为全局变量,让函数内部使用全局变量的 a,那么整个程序中出现的 都将是这个:globalaa
#!/usr/bin/env python3
a = 9
def change():
global a
print(a)
a = 100
print("Before the function call ", a)
print(“inside change function”, end=’ ‘)
change()
print("After the function call ", a)
程序中的 参数表示,print 打印后的结尾不用换行,而用空格。默认情况下 print 打印后会在结尾换行。end=’ ’
程序执行的结果,不会报错了,因为函数体内可以访问全局的变量 :a
Before the function call 9
inside change function 9
After the function call 100
在函数内使用 会有什么作用呢?尝试下面的代码:global
#!/usr/bin/env python3
def change():
global a
a = 90
print(a)
a = 9
print("Before the function call ", a)
print(“inside change function”, end=’ ')
change()
print("After the function call ", a)
程序执行的结果:
Before the function call 9
inside change function 90
After the function call 90
这里通过关键字 来告诉 a 的定义是全局的,因此在函数内部更改了 的值,函数外 的值也实际上更改了。globalaa
运行程序:
在这里插入图片描述

8.4默认参数值

函数的参数变量可以有默认值,也就是说如果我们对指定的参数变量没有给出任何值则会赋其默认值。

def test(a , b=-99):
… if a > b:
… return True
… else:
… return False
在上面的例子里,我们在函数的参数列表写出 。这表示如果调用者未给出 的值,那么 的值默认为 。这是一个关于默认参数的非常简单的例子。b = -99bb-99
你可以通过调用函数测试代码。
test(12, 23)
False
test(12)
True
有两个非常重要的地方,第一个是具有默认值的参数后面不能再有普通参数,比如 就是错误的。f(a,b=90,c)
第二个是默认值只被赋值一次,因此如果默认值是任何可变对象时会有所不同,比如列表、字典或大多数类的实例。例如,下面的函数在后续调用过程中会累积(前面)传给它的参数:
def f(a, data=[]):
… data.append(a)
… return data

print(f(1))
[1]
print(f(2))
[1, 2]
print(f(3))
[1, 2, 3]
要避免这个问题,你可以像下面这样:
def f(a, data=None):
… if data is None:
… data = []
… data.append(a)
… return data

print(f(1))
[1]
print(f(2))
[2]
在这里插入图片描述

8.5强制关键字参数

我们也能将函数的参数标记为只允许使用关键字参数。用户调用函数时将只能对每一个参数使用相应的关键字参数。

def hello(*, name=‘User’):
… print(“Hello”, name)

hello(‘wiseinsight’)
Traceback (most recent call last):
File “”, line 1, in
TypeError: hello() takes 0 positional arguments but 1 was given
hello(name=‘wiseinsight’)
Hello wiseinsight
在这里插入图片描述

了解更多,请阅读PEP-3102。

8.6文档字符串

在 Python 里我们使用文档字符串(docstrings)来说明如何使用代码,这在交互模式非常有用,也能用于自动创建文档。下面我们来看看使用文档字符串的例子。
#!/usr/bin/env python3
import math

def longest_side(a, b):
“”"
Function to find the length of the longest side of a right triangle.

:arg a: Side a of the triangle
:arg b: Side b of the triangle:return: Length of the longest side c as float
"""
return math.sqrt(a*a + b*b)

if name == ‘main’:
print(longest_side.doc)
print(longest_side(4,5))
运行程序:
在这里插入图片描述

8.7高阶函数

高阶函数(Higher-order function)或仿函数(functor)是可以接受函数作为参数的函数:
• 使用一个或多个函数作为参数
• 返回另一个函数作为输出
Python 里的任何函数都可以作为高阶函数,下面举一个简单的例子:
创建一个函数,将参数列表中每个元素都变成全大写

def high(l):
… return [i.upper() for i in l]

创建高阶函数,接受一个函数和一个列表作为参数
def test(h, l):
… return h(l)

l = [‘python’, ‘Linux’, ‘Git’]
#运行高阶函数,返回预期的结果
test(high, l)
[‘PYTHON’, ‘LINUX’, ‘GIT’]
在这里插入图片描述

阅读官方文档了解更多。

8.7.1 map 函数

map是一个在 Python 里非常有用的高阶函数。它接受一个函数和一个序列(迭代器)作为输入,然后对序列(迭代器)的每一个值应用这个函数,返回一个序列(迭代器),其包含应用函数后的结果。
举例:

lst = [1, 2, 3, 4, 5]
def square(num):
… “返回所给数字的平方.”
… return num * num

print(list(map(square, lst)))
[1, 4, 9, 16, 25]
在这里插入图片描述

8.8总结

经过本实验应当知道如何定义函数,局域变量和全局变量一定要弄清楚,参数默认值、关键字参数也需要掌握。
另外,其它高级语言常见的函数重载,Python 是没有的,这是因为 Python 有默认参数这个功能,函数重载的功能大都可以使用默认参数达到。
在后面我们还介绍了高阶函数的概念并使用了 函数。在 Python 中还有其它的高阶函数,如sorted()、filter()以及functools模块中的函数,大家可以了解一下。map()

9.1实验介绍

文件是保存在计算机存储设备上的一些信息或数据。你已经知道了一些不同的文件类型,比如你的音乐文件,视频文件,文本文件。Python 给了你一些简单的方式操纵文件。通常我们把文件分为两类,文本文件和二进制文件。文本文件是简单的文本,二进制文件包含了只有计算机可读的二进制数据。

9.1.1 知识点

• 文件打开模式
• 文件读取与写入
• with语句

9.2文件操作

本部分实验内容会实践学习以下的知识:

  1. 文件打开与关闭
  2. 文件读取与写入
    所有的实例程序都需要你在实验环境中完整的输入并执行。

9.2.1 文件打开

我们使用 函数打开文件。它需要两个参数,第一个参数是文件路径或文件名,第二个是文件的打开模式。模式通常是下面这样的:open()
• “r”,以只读模式打开,你只能读取文件但不能编辑/删除文件的任何内容
• “w”,以写入模式打开,如果文件存在将会删除里面的所有内容,然后打开这个文件进行写入
• “a”,以追加模式打开,写入到文件中的任何数据将自动添加到末尾
默认的模式为只读模式,也就是说如果你不提供任何模式, 函数将会以只读模式打开文件。我们将实验打开一个文件,不过要准备实验材料,创建一个 文件,并输入以下内容并保存:open()sample.txt
在这里插入图片描述

然后进入 Python3 打开这个文件。

fobj = open(“sample.txt”)
fobj
<_io.TextIOWrapper name=‘sample.txt’ mode=‘r’ encoding=‘UTF-8’>

9.2.2 文件关闭

打开文件后我们应该总是关闭文件。我们使用方法 完成这个操作。close()

fobj.close()
始终确保你显式关闭每个打开的文件,一旦它的工作完成你没有任何理由保持打开文件。因为程序能打开的文件数量是有上限的。如果你超出了这个限制,没有任何可靠的方法恢复,因此程序可能会崩溃。每个打开的文件关联的数据结构(文件描述符/句柄/文件锁…)都要消耗一些主存资源。因此如果许多打开的文件没用了你可以结束大量的内存浪费,并且文件打开时始终存在数据损坏或丢失的可能性。
在这里插入图片描述

9.2.3 文件读取

使用 方法一次性读取整个文件。read()

fobj = open(“sample.txt”)
fobj.read()
‘I love Python\nI love wiseinsight\n’
fobj.close()
如果你再一次调用 ,它会返回空字符串因为它已经读取完整个文件。read()
read(size)有一个可选的参数 ,用于指定字符串长度。如果没有指定 或者指定为负数,就会读取并返回整个文件。当文件大小为当前机器内存两倍时,就会产生问题。反之,会尽可能按比较大的大小读取和返回数据。sizesize
readline()能帮助你每次读取文件的一行。
fobj = open(“sample.txt”)
fobj.readline()
‘I love Python\n’
fobj.readline()
‘I love wiseinsight\n’
fobj.close()
使用 方法读取所有行到一个列表中。readlines()
fobj = open(‘sample.txt’)
fobj.readlines()
[‘I love Python\n’, ‘I love wiseinsight\n’]
fobj.close()
你可以循环遍历文件对象来读取文件中的每一行。
fobj = open(‘sample.txt’)
for x in fobj:
… print(x, end = ‘’)

I love Python
I love wiseinsight
fobj.close()
在这里插入图片描述

让我们写一个程序,命名为 test.py,这个程序接受用户输入的字符串作为将要读取的文件的文件名,并且在屏幕上打印文件内容。
#!/usr/bin/env python3
name = input("Enter the file name: ")
fobj = open(name)
print(fobj.read())
fobj.close()
运行程序:
在这里插入图片描述

9.2.4 文件写入

在目录下:/home/wiseinsight
创建txt文件:
sudo touch ircnicks.txt
修改权限:
sudo chmod 666 ircnicks.txt
之后,让我们通过 方法打开文件然后我们随便写入一些文本。write()

fobj = open(“ircnicks.txt”, ‘w’)
fobj.write(‘powerpork\n’)
fobj.write(‘indrag\n’)
fobj.write(‘mishti\n’)
fobj.write(‘sankarshan’)
fobj.close()
现在读取我们刚刚创建的文件。
fobj = open(‘ircnicks.txt’)
s = fobj.read()
fobj.close()
print(s)
powerpork
indrag
mishti
sankarshan
在这里插入图片描述

9.3文件操作示例程序

本部分实验将通过两个实例程序来实践之前学习的文件操作方法:

  1. 拷贝文件程序
  2. 文本文件信息统计程序
    所有的实例程序都需要你在实验环境中完整的输入并执行。

9.3.1 拷贝文件

在这个例子里我们拷贝给定的文本文件到另一个给定的文本文件。
先创建一个空的txt文件:
sudo touch ircnicks2.txt
添加权限:
sudo chmod 666 ircnicks2.txt
在目录下:/home/wiseinsight
编辑 :copyfile.py
sudo vim copyfile.py
修改权限:
sudo chmod +x copyfile.py
写入以下代码:
#!/usr/bin/env python3
import sys
if len(sys.argv) < 3:
print(“Wrong parameter”)
print(“./copyfile.py file1 file2”)
sys.exit(1)
f1 = open(sys.argv[1])
s = f1.read()
f1.close()
f2 = open(sys.argv[2], ‘w’)
f2.write(s)
f2.close()
运行程序:
./copyfile.py ircnicks.txt ircnicks2.txt
在这里插入图片描述

你可以看到我们在这里使用了一个新模块 。包含所有命令行参数。这个程序的功能完全可以使用 shell 的 命令替代:在 后首先输入被拷贝的文件的文件名,然后输入新文件名。syssys.argvcpcp
sys.argv的第一个值是命令自身的名字,下面这个程序打印命令行参数。
#!/usr/bin/env python3
import sys
print(“First value”, sys.argv[0])
print(“All values”)
for i, x in enumerate(sys.argv):
print(i, x)
运行程序:
在这里插入图片描述

这里我们用到了一个新函数 ,在序列中循环时,索引位置和对应值可以使用它同时得到。enumerate(iterableobject)

9.3.2 文本文件相关信息统计

让我们试着编写一个程序,对任意给定文本文件中的制表符、行、空格进行计数。
代码写入文件 :/home/wiseinsight/parsefile.py
#!/usr/bin/env python3

import os
import sys

def parse_file(path):
“”"
分析给定文本文件,返回其空格、制表符、行的相关信息

:arg path: 要分析的文本文件的路径:return: 包含空格数、制表符数、行数的元组
"""
fd = open(path)
i = 0
spaces = 0
tabs = 0
for i,line in enumerate(fd):spaces += line.count(' ')tabs += line.count('\t')
# 现在关闭打开的文件
fd.close()# 以元组形式返回结果
return spaces, tabs, i + 1

def main(path):
“”"
函数用于打印文件分析结果

:arg path: 要分析的文本文件的路径
:return: 若文件存在则为 True,否则 False
"""
if os.path.exists(path):spaces, tabs, lines = parse_file(path)print("Spaces {}. tabs {}. lines {}".format(spaces, tabs, lines))return True
else:return False

if name == ‘main’:
if len(sys.argv) > 1:
main(sys.argv[1])
else:
sys.exit(-1)
sys.exit(0)
运行程序:
在这里插入图片描述

你可以看到程序有两个函数, 和 , 函数真正的分析文件并返回结果,然后在 函数里打印结果。通过分割代码到一些更小的单元(函数)里,能帮助我们组织代码库并且也更容易为函数编写测试用例。main()parse_file()parse_filemain()

9.4使用 语句with

在实际情况中,我们应该尝试使用 语句处理文件对象,它会在文件用完后会自动关闭,就算发生异常也没关系。它是 try-finally 块的简写:with

with open(‘sample.txt’) as fobj:
… for line in fobj:
… print(line, end = ‘’)

I love Python
I love wiseinsight
在这里插入图片描述

9.5总结

回顾本节实验知识点:
• 文件打开模式
• 文件读取与写入
• with语句
本实验我们学习了文件的打开与读写,在读写完毕后一定要记得关闭文件,或者使用 with 语句也是极好的。在 Linux 中你还需要注意你操作的文件的权限。Linux 有一个思想是"一切皆文件",这在实验最后的 的实现中得到了体现。lscpu

10.1实验介绍

在这个实验我们学习 Python 的异常以及如何在你的代码中处理它们。

10.1.1 知识点

• 名称错误
• 类型错误
• 异常处理(try…除了)
• 异常抛出(raise)
• 最后 子句

10.2常见异常

在程序执行过程中发生的任何错误都是异常。每个异常显示一些相关的错误信息,比如你在 Python3 中使用 Python2 独有的语法就会发生 :SyntaxError
在这里插入图片描述

不小心在行首多打了一个空格就会产生 :IndentationError
在这里插入图片描述

10.2.1 名称错误

当访问一个未定义的变量则会发生NameError
在这里插入图片描述

最后一行包含了错误的详细信息,其余行显示它是如何发生(或什么引起该异常)的详细信息。

10.2.2 类型错误

TypeError也是一种经常出现的异常。当操作或函数应用于不适当类型的对象时引发,一个常见的例子是对整数和字符串做加法。
在这里插入图片描述

常发生的异常
异常名称 描述
系统退出 解释器请求退出
键盘中断 用户中断执行(通常是输入^C)
停止操作 迭代器没有更多的值
生成器导出 生成器(generator)发生异常来通知退出
标准错误 所有的内建标准异常的基类
算术错误 所有数值计算错误的基类
浮点错误 浮点计算错误
溢出错误 数值运算超出最大限制
ZeroDivisionError 除(或取模)零 (所有数据类型)
断言错误 断言语句失败
导入错误 导入模块/对象失败
索引错误 序列中没有没有此索引(索引)【越界】
内存错误 内存溢出错误(对于Python 解释器不是致命的)
名称错误 未声明/初始化对象 (没有属性)
运行时错误 一般的运行时错误
未实现错误 尚未实现的方法
语法错误 Python 语法错误
缩进错误 缩进错误
类型错误 对类型无效的操作
系统错误 一般的解释器系统错误
值错误 传入无效的参数

10.3处理异常

我们使用 块来处理任意异常。基本的语法像这样:try…except
try:
statements to be inside try clause
statement2
statement3

except ExceptionName:
statements to evaluated in case of ExceptionName happens
它以如下方式工作:
• 首先,执行 子句 (在try和except关键字之间的部分)。try
• 如果没有异常发生, 子句 在try语句执行完毕后就被忽略了。except
• 如果在 子句执行过程中发生了异常,那么该子句其余的部分就会被忽略。try
如果异常匹配于except关键字后面指定的异常类型,就执行对应的 子句。然后继续执行try语句之后的代码。except
• 如果发生了一个异常,在except子句中没有与之匹配的分支,它就会传递到上一级try语句中。
如果最终仍找不到对应的处理语句,它就成为一个未处理异常,终止程序运行,显示提示信息。
下面的例子展示了这些情况:

def get_number():
… “Returns a float number”
… number = float(input("Enter a float number: "))
… return number

while True:
… try:
… print(get_number())
… except ValueError:
… print(“You entered a wrong value.”)

Enter a float number: 45.0
45.0
Enter a float number: 24,0
You entered a wrong value.
Enter a float number: Traceback (most recent call last):
File “”, line 3, in
File “”, line 3, in get_number
KeyboardInterrupt
在这里插入图片描述

首先我输入了一个合适的浮点值,解释器返回输出这个值。
然后我输入以逗号分隔的值,抛出 异常, 子句捕获之,并且打印出错误信息。ValueErrorexcept
第三次我按下 ,导致了 异常发生,这个异常并未在 块中捕获,因此程序执行被中止。Ctrl + CKeyboardInterruptexcept
一个空的 语句能捕获任何异常。阅读下面的代码:except

try:
… input() # 输入的时候按下 Ctrl + C 产生 KeyboardInterrupt
… except:
… print(“Unknown Exception”)

Unknown Exception

10.3.1 抛出异常

使用 语句抛出一个异常。raise

raise ValueError(“A value error happened.”)
Traceback (most recent call last):
File “”, line 1, in
ValueError: A value error happened.
我们可以捕获任何其它普通异常一样,来捕获这些异常。
try:
… raise ValueError(“A value error happened.”)
… except ValueError:
… print(“ValueError in our code.”)

ValueError in our code.
在这里插入图片描述

10.3.2 定义清理行为

try语句还有另一个可选的 子句,目的在于定义在任何情况下都一定要执行的功能。例如:finally

try:
… raise KeyboardInterrupt
… finally:
… print(‘Goodbye, world!’)

Goodbye, world!
KeyboardInterrupt
Traceback (most recent call last):
File “”, line 2, in ?
在这里插入图片描述

不管有没有发生异常, 子句 在程序离开 后都一定会被执行。当 语句中发生了未被 捕获的异常(或者它发生在 或 子句中),在 子句执行完后它会被重新抛出。finallytrytryexceptexceptelsefinally
在真实场景的应用程序中, 子句用于释放外部资源(文件或网络连接之类的),无论它们的使用过程中是否出错。finally

10.4异常逻辑处理示例

10.4.1 要求:

  1. 用户能够通过命令行参数输入分钟数,不要使用 ,命令行参数可以使用 来提取。例如程序执行为 ,传入的参数 80 就是分钟数,程序需要打印出相应的小时数和分钟数,输出为 。inputsys.argv./MinutesToHours.py 801 H, 20 M
  2. 如果用户输入的是一个负值,程序需要 raise 来抛出 异常。ValueError
  3. Hours()函数调用的时候,需要使用 处理异常。获取异常后,在屏幕上打印出 提示用户输入的值有误。try…exceptParameter Error

10.4.2 参考代码

MinutesToHours.py参考代码:
#!/usr/bin/env python3
import sys
转换函数
def Hours(minute):
如果为负数则 raise 异常
if minute < 0:
raise ValueError(“Input number cannot be negative”)
else:
print(“{} H, {} M”.format(int(minute / 60), minute % 60))
#函数调用及异常处理逻辑
try:
Hours(int(sys.argv[1]))
except:
print(“Parameter Error”)

10.4.3 注意

• sys.argv获取命令行参数,注意获取的参数为字符串,可以使用 将字符串转为整数,此处也可能会出现异常情况,例如输入为 “abcd” 是无法转为整数的int()
• raise语句
• try…except语句

10.5总结

本实验我们知道了异常是什么,然后怎样处理异常以及抛出异常。记得在前面说过的 语句吧,它是 块的简写,使用 语句能保证文件始终被关闭。withtry-finallywith
异常是什么?其实异常是一种 ,而类将会在下一个实验介绍。类

11.1实验介绍

在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。
还有Python 模块相关知识。包括模块的概念和导入方法,包的概念和使用,第三方模块的介绍,命令行参数的使用等。

11.1.1 知识点

• 类的定义
• 对象初始化
• 模块的导入
• 默认/第三方模块介绍
• 命令行参数

11.2类

本部分实验中将通过定义一些简单的 Python 类,来学习 Python 面向对象编程的基本概念。
实验安排如下:

  1. 定义简单的类
  2. init 方法
  3. Python 中的继承
  4. 多继承
  5. 删除对象
  6. 属性读取方法
  7. @property装饰器

11.2.1 定义类

在写你的第一个类之前,你应该知道它的语法。我们以下面这种方式定义类:
class nameoftheclass(parent_class):
statement1
statement2
statement3
在类的声明中你可以写任何 Python 语句,包括定义函数(在类中我们称为方法)。

class MyClass(object):
… “”“A simple example class”“”
… i = 12345
… def f(self):
… return ‘hello world’

11.2.2 init 方法

类的实例化使用函数符号。只要将类对象看作是一个返回新的类实例的无参数函数即可。例如(假设沿用前面的类):
x = MyClass()
以上创建了一个新的类实例并将该对象赋给局部变量 。x
这个实例化操作创建一个空的对象。很多类都倾向于将对象创建为有初始状态的。因此类可能会定义一个名为 的特殊方法,像下面这样:init()
def init(self):
self.data = []
类定义了 方法的话,类的实例化操作会自动为新创建的类实例调用 方法。所以在下例中,可以这样创建一个新的实例:init()init()
x = MyClass()
当然,出于弹性的需要, 方法可以有参数。事实上,参数通过 传递到类的实例化操作上。例如:init()init()

class Complex:
… def init(self, realpart, imagpart):
… self.r = realpart
… self.i = imagpart

x = Complex(3.0, -4.5)
x.r, x.i
(3.0, -4.5)
在这里插入图片描述

11.2.3 继承

当一个类继承另一个类时,它将继承父类的所有功能(如变量和方法)。这有助于重用代码。
在下一个例子中我们首先创建一个叫做 的类,然后创建两个派生类 和 。当两个类都从 类继承时,它们的类除了会有 类的所有方法还会有自身用途的新方法和新变量。PersonStudentTeacherPersonPerson

11.2.3.1 student_teacher.py

代码写入文件 :student_teacher.py
#!/usr/bin/env python3

class Person(object):
“”"
返回具有给定名称的 Person 对象
“”"

def __init__(self, name):self.name = namedef get_details(self):"""返回包含人名的字符串"""return self.name

class Student(Person):
“”"
返回 Student 对象,采用 name, branch, year 3 个参数
“”"

def __init__(self, name, branch, year):Person.__init__(self, name)self.branch = branchself.year = yeardef get_details(self):"""返回包含学生具体信息的字符串"""return "{} studies {} and is in {} year.".format(self.name, self.branch, self.year)

class Teacher(Person):
“”"
返回 Teacher 对象,采用字符串列表作为参数
“”"
def init(self, name, papers):
Person.init(self, name)
self.papers = papers

def get_details(self):return "{} teaches {}".format(self.name, ','.join(self.papers))

person1 = Person(‘Sachin’)
student1 = Student(‘Kushal’, ‘CSE’, 2005)
teacher1 = Teacher(‘Prashad’, [‘C’, ‘C++’])

print(person1.get_details())
print(student1.get_details())
print(teacher1.get_details())
运行程序
在这里插入图片描述

在这个例子中你能看到我们是怎样在 类和 类中调用 类的 方法。StudentTeacherPerson__init__
我们也在 类和 类中重写了 类的 方法。StudentTeacherPersonget_details()
因此,当我们调用 和 的 方法时,使用的是各自类( 和 )中定义的方法。student1teacher1get_details()StudentTeacher

11.2.4 多继承

一个类可以继承自多个类,具有父类的所有变量和方法,语法如下:
class MyClass(Parentclass1, Parentclass2,…):
def init(self):
Parentclass1.init(self)
Parentclass2.init(self)

11.2.5 删除对象

现在我们已经知道怎样创建对象,现在我们来看看怎样删除一个对象。我们使用关键字 来做到这个。del

s = “I love you”
del s
s
Traceback (most recent call last):
File “”, line 1, in
NameError: name ‘s’ is not defined
在这里插入图片描述

del实际上使对象的引用计数减少一,当对象的引用计数变成零的时候,垃圾回收器会删除这个对象。

11.2.6 属性(属性)读取方法

在 Python 里请不要使用属性(attributes)读取方法(getters和setters)。如果你之前学过其它语言(比如 Java),你可能会想要在你的类里面定义属性读取方法。请不要这样做,直接使用属性就可以了,就像下面这样:

class Student(object):
… def init(self, name):
… self.name = name

std = Student(“Kushal Das”)
print(std.name)
Kushal Das
std.name = “Python”
print(std.name)
Python
在这里插入图片描述

11.2.7 装饰器

你可能想要更精确的调整控制属性访问权限,你可以使用 装饰器, 装饰器就是负责把一个方法变成属性调用的。@property@property
下面有个银行账号的例子,我们要确保没人能设置金额为负,并且有个只读属性 cny 返回换算人民币后的金额。
代码写入文件/home/wiseinsight/property.py
#!/usr/bin/env python3

class Account(object):
“”“账号类,
amount 是美元金额.
“””
def init(self, rate):
self.__amt = 0
self.rate = rate

@property
def amount(self):"""账号余额(美元)"""return self.__amt@property
def cny(self):return self.__amt * self.rate@amount.setter
def amount(self, value):if value < 0:print("Sorry, no negative amount in the account.")returnself.__amt = value

if name == ‘main’:
acc = Account(rate=6.6) # 基于课程编写时的汇率
acc.amount = 20
print(“Dollar amount:”, acc.amount)
print(“In CNY:”, acc.cny)
acc.amount = -100
print(“Dollar amount:”, acc.amount)
运行程序:
在这里插入图片描述

11.3模块

到目前为止,我们在 Python 解释器中写的所有代码都在我们退出解释器的时候丢失了。但是当人们编写大型程序的时候他们会倾向于将代码分为多个不同的文件以便使用,调试以及拥有更好的可读性。在 Python 中我们使用模块来到达这些目的。模块是包括 Python 定义和声明的文件。文件名就是模块名加上 后缀。.py 现在我们来看看模块是怎样工作的。创建一个 文件。文件内容如下:bars.py

“”"
Bars Module
这是一个打印不同分割线的示例模块
“”"
def starbar(num):
“”"打印 * 分割线

:arg num: 线长
"""
print('*' * num)

def hashbar(num):
“”"打印 # 分割线

:arg num: 线长
"""
print('#' * num)

def simplebar(num):
“”"打印 - 分割线

:arg num: 线长
"""
print('-' * num)

给该文件赋予执行权限
chmod +x bars.py
现在我们启动解释器然后导入我们的模块。

import bars
import sys
sys.path.append(‘/home/wiseinsight’)
我们必须使用模块名来访问模块内的函数。
bars.simplebar(10)


bars.hashbar(10)
##########
bars.starbar(10)


11.3.1 导入模块

有不同的方式导入模块。我们已经看到过一种了。你甚至可以从模块中导入指定的函数。这样做:

from bars import simplebar, starbar
simplebar(20)


在这里插入图片描述

你也可以使用 导入模块中的所有定义,然而这并不是推荐的做法。from module import *

11.4默认模块

现在你安装 Python 的时候会附带安装不同的模块,你可以按需使用它们,也可以为其它特殊用途安装新模块。在下面的几个例子中,我们将要看到同样例子很多。
在这里插入图片描述

上面的例子展示了怎样获得你系统中安装的所有模块的列表。在这里就不粘贴它们了,因为这是一个很大的列表。
你也能在解释器里使用 函数查找任何模块/类的文档。如果你想要知道字符串所有可用的方法,你可以像下面这样做:help()

help(str)
按返回q

11.4.1 os 模块

os模块提供了与操作系统相关的功能。你可以使用如下语句导入它:

import os
getuid()函数返回当前进程的有效用户 id。
os.getuid()
500
getpid()函数返回当前进程的 id。返回父进程的 id。getppid()
os.getpid()
16150
os.getppid()
14847
uname()函数返回识别操作系统的不同信息,在 Linux 中它返回的详细信息可以从 命令得到。返回的对象是一个元组,。uname -auname()(sysname, nodename, release, version, machine)
os.uname()
(‘Linux’, ‘d80’, ‘2.6.34.7-56.fc13.i686.PAE’, ‘#1 SMP Wed Sep 15 03:27:15 UTC 2010’, ‘i686’)
在这里插入图片描述

getcwd() 函数返回当前工作目录。则是更改当前目录到 path。在例子中我们首先看到当前工作目录是 ,然后我们更改当前工作目录到 并再一次查看当前工作目录。chdir(path)/home/wiseinsight/Code

os.getcwd()
‘/home’
os.chdir(‘wiseinsight’)
os.getcwd()
‘/home/wiseinsight’
所以现在让我们使用 os 模块提供的另一个函数来创建一个自己的函数,它将列出给定目录下的所有文件和目录。
def view_dir(path=‘.’):
“”"
这个函数打印给定目录中的所有文件和目录
:args path: 指定目录,默认为当前目录
“”"
names = os.listdir(path)
names.sort()
for name in names:
print(name, end =’ ‘)
print()
使用例子中的 函数。view_dir()
view_dir(’/')
.bashrc .dockerenv .profile bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
os 模块还有许多非常有用的函数,你可以在这里阅读相关内容。
在这里插入图片描述

11.5总结

实验知识点回顾:
• 类的定义
• 对象初始化
• 模块的导入
• 默认/第三方模块介绍
• 命令行参数
本实验我们了解了类的定义,类的继承以及多继承,并且最后我们还接触了装饰器这个概念,本质上,装饰器也是一种高阶函数。
也了解了什么是模块,模块怎样导入,举例了 os 模块的使用。Python 吸引人的一点是其有众多的模块可以使用,对于自带模块,可以看看 Python3 的官方文档,对于第三方模块,可以在PyPI上找找。很多时候你都能找到合适的包帮你优雅的完成部分工作。

相关文章:

  • linux blueZ 第四篇:BLE GATT 编程与自动化——Python 与 C/C++ 实战
  • CSS3布局方式介绍
  • 性能提升手段--池化技术
  • PySpark实现ABC_manage_channel逻辑
  • 精益数据分析(25/126):关键指标驱动业务发展
  • WPF实现数字孪生示例
  • 使用PyTorch实现简单图像识别(基于MNIST手写数字数据集)的完整代码示例,包含数据加载、模型定义、训练和预测全流程
  • 关于使用 读光-文字检测-DBNet行检测模型-中英-通用领域,版本问题
  • 《P1950 长方形》
  • 前端与Rust后端交互:跨越语言鸿沟 (入门系列三)
  • 开源AI视频FramePack发布:6GB显卡本地运行
  • LIDC-IDRI数据集切割代码教程【pylidc库】
  • 小刚说C语言刷题——1109加密四位数
  • Dify 使用 excel 或者 csv 文件创建知识库
  • Java单链表题目
  • Linux线程与进程:探秘共享地址空间的并发实现与内
  • Three.js + React 实战系列-3D 个人主页:构建 Hero 场景组件(项目核心)✨
  • 16.【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--微服务基础工具与技术--Github Action
  • 高精度3D圆弧拟合 (C++)
  • 详解 Network.framework:iOS 网络开发的新基石
  • 美乌总统梵蒂冈会谈,外交部:望有关各方继续通过对话谈判解决危机
  • 新剧|反谍大剧《绝密较量》央一开播,张鲁一高圆圆主演
  • 稳就业稳经济五方面若干举措将成熟一项出台一项
  • IPO周报|4月最后2只新股周一申购,今年以来最低价股来了
  • 国务院同意在海南全岛和秦皇岛等15个城市(地区)设立跨境电子商务综合试验区
  • 网络达人“拿”别人的视频为自己带货赚佣金,法院判决赔偿1.4万元