“笨办法”学Python 3基础篇 第一部分-打印与输入
“笨办法”学Python 3基础篇 第二部分-文件操作
“笨办法”学Python 3基础篇 第三部分-函数
“笨办法”学Python 3基础篇 第四部分-数据容器与程序结构
“笨办法”学Python 3基础篇 第五部分-面向对象的类
“笨办法”学Python 3基础篇 第六部分-项目骨架与自动测试
“笨办法”学Python 3基础篇 第七部分-搭建简易的网站
上个礼拜一直在忙本人学校教学大纲修订的任务,自3月23日至3月30日止,期间耗费了较多精力,因此本来计划的上周要继续总结假期学习内容的博文也来不及写了。昨天又是上课又是开会,回家还得教育孩子,实在是没精力敲打键盘了。今天终于得空,继续进行Python3 假期学习内容的总结。
本篇主要是总结常用的程序逻辑结构-分支和循环,并将分支、循环和数据容器-列表相结合进行总结。
在学C语言或者Verilog HDL语言时,进行算法级的描述常用到的逻辑控制结构为分支结构(也叫做条件结构)和循环结构。分支结构用于进行条件的判断,从而根据判断结果做出决定,以 if、elif、else 的使用最常见。循环结构则是用于逻辑的迭代,数据的遍历,以 for、while 的使用最常见。如果我们不想只局限于打印和输入,那么就必然会用到这两个程序逻辑结构来设计更复杂的功能。
不同于C语言,在Python3 中分支的基本语法结构为:
分支结构以 if 开头,后接布尔表达式和 : 号。行尾冒号的作用是告诉Python接下来你要创建一个新代码块,下接的代码块必修进行缩进,以此来告诉Python这些代码处于该段代码快中,与创建函数时相同。根据布尔表达式的真或假,选择运行 if 代码块还是 elif 代码块。如果所有情况都不满足,则执行默认的 else 代码块。
现在,我们可以用分支结构来解决一个简单的问题:
设计一个简易整数口算训练机,提供口算习题并能够判断口算结果是否正确
分析这个问题,这样一个简单的口算训练机,需要实现如下功能:
为了生成随机数,我们需要import一个叫做 random 的模块,这是一个Python安装时就有的系统模块,不需要额外安装扩展包。然后通过random模块去调用不同的随机数生成方法,常用的为:
来看这样一段代码:
import random
print(random.random())
print(random.random()*100)
print(random.uniform(100,101))
print(random.randint(0,100))
第一行代码为引入random模块,后面四行代码分别实现生成[0,1)的随机实数、生成[0,100)的随机实数、生成[100, 101)的随机实数、生成0-100的随机整数。在PowerShell运行后,结果为:
在掌握了random模块生成随机数的方法后,我们就需要将生成的随机数按照数值大小划分出两个部分,即[0,50)和[50,100)这两个部分。每个部分作为一个判断条件,执行减法函数或加法函数的调用,具体的分支结构(伪代码)为:
if 随机数处于[0,50) :
调用加法函数add
else :
调用减法函数sub
具体的实现代码为
import random
def gen():
op1 = random.randint(0, 100)
op2 = random.randint(0, 100)
op3 = random.random()*100
if op3 < 50:
return add(op1, op2)
elif op3 >= 50 and op1 >= op2:
return sub(op1, op2)
else:
return sub(op2, op1)
在这段代码中,我们通过 gen() 这个函数来负责随机数和随机运算符的生成。op1 和 op2是运算时的两个操作数,通过op3来判断生成加法还是减法。如果op3小于50,则调用加法函数实现 op1 + op2;如果op3大于等于50且op1大于op2,返回sub(op1,op2), 实现 op1 - op2; 否则返回sub(op2, op1), 实现 op2 - op1。
运用“笨办法”学Python 3基础篇 第三部分-函数
中的设计方法,加法和减法函数功能为:
具体的代码为:
from sys import exit
def add(augend, addend):
print(f"{augend} + {addend} = ", end = "")
result = int(input())
if result == augend + addend:
print(f"The result is true.")
exit(0)
else:
print(f"The result is false.")
exit(0)
def sub(augend, subend):
print(f"{augend} - {subend} = ", end = "")
result = int(input())
if result == augend - subend:
print(f"The result is true.")
exit(0)
else:
print(f"The result is false.")
exit(0)
为了计算成功后,能够退出脚本, 我们引入了exit模块。通过使用exit(0)来正常退出程序,回到PowerShell。
完成了随机数生成、随机运算符和运算函数后,剩下的就是综合了。综合后的代码为:
from sys import exit
import random
def gen():
op1 = random.randint(0, 100)
op2 = random.randint(0, 100)
op3 = random.random()*100
if op3 < 50:
return add(op1, op2)
elif op3 >= 50 and op1 >= op2:
return sub(op1, op2)
else:
return sub(op2, op1)
def add(augend, addend):
print(f"{augend} + {addend} = ", end = "")
result = int(input())
if result == augend + addend:
print(f"The result is true.")
exit(0)
else:
print(f"The result is false.")
exit(0)
def sub(augend, subend):
print(f"{augend} - {subend} = ", end = "")
result = int(input())
if result == augend - subend:
print(f"The result is true.")
exit(0)
else:
print(f"The result is false.")
exit(0)
print("Welcome! Are you ready to start a math test?")
print("Y/N", end='')
decide = input('> ')
if (decide == 'Y'):
gen()
else:
print("Coward!")
当然,这里少不了用分支结构设计一下对话方式,通过输入Y来执行gen()函数,通过N来输出字符串。运行PowerShell后得到的结果为
循环结构是另一种常用的逻辑控制结构。常用到的是for和while。
在开始使用for循环之前,我们需要在某个位置存放循环的结果,也就是需要一个数据的容器。最好的方法是使用列表。列表的定义非常简单,以 [ 开头打开列表,然后写下要放入列表的东西,用逗号隔开,就跟函数的参数一样,最后需要用右括号 ] 表明列表结束。例如:
如果想要遍历hairs这个列表的所有元素,此时我们就需要用到for循环了。for循环的基本语法结构为:
for 变量 in 序列:
代码
else:
代码
这里的序列可以是列表或者字符串, else后面的是可选项。下面我们来看如何遍历hairs这个列表,并打印出每个元素。代码如下:
hairs = ['brown', 'blond', 'red']
for color in hairs:
print(f"Your hair is {color}!")
for number in range(3):
print(f"My hair is {hairs[number]}, too!")
在这段代码中,第一个for循环将hairs列表中的元素在每次循环时依次赋值给了color,实现了列表元素的遍历。第二个for循环中序列则采用了range(3)函数,实现了0,1,2三个整数的遍历。每遍历一个整数,number变量就赋值为该整数并从hairs列表中切片出对应元素。PowerShell运行结果如图所示。
如果要使用while循环来实现,则首先我们得了解while循环的基本语法结构:
while(布尔条件):
代码1
else:
代码2
当布尔条件为真时,执行代码1;否则执行else的代码块。当然else是可以省略的。
用while代替for循环来编列hairs列表遇到最主要的问题是需要找出布尔条件。可以采用计数器+列表元素的个数来作为布尔条件实现循环的结束。具体代码如下:
hairs = ['brown', 'blond', 'red']
count = 0
while(count < len(hairs)):
print(f"Her hair is {hairs[count]}!")
count += 1
在该段代码中,定义了一个计数器count,每遍历列表中的一个元素,累计加1。通过len()获得了列表元素的个数。当计数器count等于列表元素个数时跳出循环。PoweShell运行结果为:
之前我们的口算训练程序每次只能做一次运算。现在我们可以用逻辑循环结构来为口算训练程序添加如下功能:
具体的实现代码为:
from sys import exit
import random
def gen():
op1 = random.randint(0, 100)
op2 = random.randint(0, 100)
op3 = random.random()*100
if op3 < 50:
return add(op1, op2)
elif op3 >= 50 and op1 >= op2:
return sub(op1, op2)
else:
return sub(op2, op1)
def add(augend, addend):
print(f"{augend} + {addend} = ", end = "")
result = int(input())
if result == augend + addend:
return 1
else:
return 0
def sub(augend, subend):
print(f"{augend} - {subend} = ", end = "")
result = int(input())
if result == augend - subend:
return 1
else:
return 0
print("Welcome! Are you ready to start a math test?")
print("Y/N", end='')
decide = input('> ')
if (decide == 'N'):
print("Coward!")
exit(0)
else:
print("How many exercises do you want to try?", end='')
count = int(input('> '))
score = 0
while count != 0:
score += gen()
count -= 1
print(f"Your final test score is {score}.")
exit(0)
在这段代码中,我们对add()和sub()函数做了稍微的修改,不再让它们打印出每次计算的结果,而是返回1或者是0。在程序控制段,修改了条件分支的顺序,避免了while循环和if条件分支程序块的语法错误。同时,通过count变量实现了口算题的计数,通过while循环实现了正确率score的累计加1。循环结束条件则为计数器递减为0。最后打印出正确率结果并启用exit(0)退出程序。
PoweShell的运行结果为:
在4.1和4.2节中,我们已经简单接触到了列表,实现了列表元素的遍历。当然还可以对列表的元素做很多操作, 比如添加和弹出元素等,具体可参考列表list。
接下来,我们将运用列表添加元素来继续解决口算练习器的问题:
用户能够浏览上一次口算训练做错的题目和自己的答案
为了实现这一功能,我们需要创建一个列表mistakes,用来存储错题和正确的答案。然后通过for 循环,遍历mistakes列表中的每个错题,并打印出来。具体的代码为:
from sys import exit
import random
def gen():
op1 = random.randint(0, 100)
op2 = random.randint(0, 100)
op3 = random.random()*100
if op3 < 50:
return add(op1, op2)
elif op3 >= 50 and op1 >= op2:
return sub(op1, op2)
else:
return sub(op2, op1)
def add(augend, addend):
print(f"{augend} + {addend} = ", end = "")
result = int(input())
if result == augend + addend:
return 1
else:
mistakes.append(f'{augend} + {addend} = {result}, the right answer is {augend + addend}' )
return 0
def sub(augend, subend):
print(f"{augend} - {subend} = ", end = "")
result = int(input())
if result == augend - subend:
return 1
else:
mistakes.append(f'{augend} - {subend} = {result}, the right answer is {augend - subend}')
return 0
print("Welcome! Are you ready to start a math test?")
print("Y/N", end='')
decide = input('> ')
if (decide == 'N'):
print("Coward!")
exit(0)
else:
mistakes = []
print("How many exercises do you want to try?", end='')
count = int(input('> '))
success = count
score = 0
while count != 0:
score += gen()
count -= 1
if score == success:
print(f"Congratulations! You got all exercises right!")
exit(0)
else:
print(f"Your final test score is {score}.")
print("Here is your wrong record: ")
for var in mistakes:
print(var)
exit(0)
代码的修改部分主要为定义了一个名为mistakes的空列表,并在add和sub函数中采用了mistakes.append实现了列表元素的添加(默认从列表末尾添加,具体用法可参考列表list)。结果为:
数据容器更重要的一个概念是:字典。这篇文章由于中途有事,又写了两天,没有来得及写字典。后面要加快进度,把字典放在后续总结,并多以案例来总结学到的基本编程理论,这样能更快速的消化。