天天看点

“笨办法”学Python 3基础篇 - 数据容器与程序结构“笨办法”学Python 3基础篇系列文章前言4.1 程序逻辑结构-分支 if、elif、else4.2 程序逻辑结构-循环 for 和 while4.3 更复杂的列表操作结语

“笨办法”学Python 3基础篇系列文章

“笨办法”学Python 3基础篇 第一部分-打印与输入

“笨办法”学Python 3基础篇 第二部分-文件操作

“笨办法”学Python 3基础篇 第三部分-函数

“笨办法”学Python 3基础篇 第四部分-数据容器与程序结构

“笨办法”学Python 3基础篇 第五部分-面向对象的类

“笨办法”学Python 3基础篇 第六部分-项目骨架与自动测试

“笨办法”学Python 3基础篇 第七部分-搭建简易的网站

第四部分 数据容器与程序结构

  • “笨办法”学Python 3基础篇系列文章
  • 前言
  • 4.1 程序逻辑结构-分支 if、elif、else
    • 4.1.1 语法格式
    • 4.1.2 让我们来做一个简易口算训练器
      • 4.1.2.1 随机数 - random用法
      • 4.1.2.2 生成随机运算符 - if + else + random
      • 4.1.2.3 运算函数
      • 4.1.2.4 综合
  • 4.2 程序逻辑结构-循环 for 和 while
    • 4.2.1 for + 列表
    • 4.2.2 while + 列表
    • 4.2.3 挑战一个更复杂的口算训练器
  • 4.3 更复杂的列表操作
  • 结语

前言

上个礼拜一直在忙本人学校教学大纲修订的任务,自3月23日至3月30日止,期间耗费了较多精力,因此本来计划的上周要继续总结假期学习内容的博文也来不及写了。昨天又是上课又是开会,回家还得教育孩子,实在是没精力敲打键盘了。今天终于得空,继续进行Python3 假期学习内容的总结。

本篇主要是总结常用的程序逻辑结构-分支和循环,并将分支、循环和数据容器-列表相结合进行总结。

4.1 程序逻辑结构-分支 if、elif、else

在学C语言或者Verilog HDL语言时,进行算法级的描述常用到的逻辑控制结构为分支结构(也叫做条件结构)和循环结构。分支结构用于进行条件的判断,从而根据判断结果做出决定,以 if、elif、else 的使用最常见。循环结构则是用于逻辑的迭代,数据的遍历,以 for、while 的使用最常见。如果我们不想只局限于打印和输入,那么就必然会用到这两个程序逻辑结构来设计更复杂的功能。

4.1.1 语法格式

不同于C语言,在Python3 中分支的基本语法结构为:

“笨办法”学Python 3基础篇 - 数据容器与程序结构“笨办法”学Python 3基础篇系列文章前言4.1 程序逻辑结构-分支 if、elif、else4.2 程序逻辑结构-循环 for 和 while4.3 更复杂的列表操作结语

分支结构以 if 开头,后接布尔表达式和 : 号。行尾冒号的作用是告诉Python接下来你要创建一个新代码块,下接的代码块必修进行缩进,以此来告诉Python这些代码处于该段代码快中,与创建函数时相同。根据布尔表达式的真或假,选择运行 if 代码块还是 elif 代码块。如果所有情况都不满足,则执行默认的 else 代码块。

4.1.2 让我们来做一个简易口算训练器

现在,我们可以用分支结构来解决一个简单的问题:

设计一个简易整数口算训练机,提供口算习题并能够判断口算结果是否正确

分析这个问题,这样一个简单的口算训练机,需要实现如下功能:

  1. 用随机数生成口算的操作数;
  2. 用随机数和分支结构生成运算符(加法和减法);
  3. 用函数求出正确答案;
  4. 提问与等待解答;
  5. 分支结构判断口算结果,做出对错决定。

4.1.2.1 随机数 - random用法

为了生成随机数,我们需要import一个叫做 random 的模块,这是一个Python安装时就有的系统模块,不需要额外安装扩展包。然后通过random模块去调用不同的随机数生成方法,常用的为:

  • random.random() : 返回生成的一个实数,在[0,1)范围内;
  • random.uniform(num1,num2) : 返回生成的一个实数,范围在[num1,num2)之间;
  • random.randint(num1,num2): 返回生成的一个整数,范围为num1到num2。

来看这样一段代码:

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运行后,结果为:

“笨办法”学Python 3基础篇 - 数据容器与程序结构“笨办法”学Python 3基础篇系列文章前言4.1 程序逻辑结构-分支 if、elif、else4.2 程序逻辑结构-循环 for 和 while4.3 更复杂的列表操作结语

4.1.2.2 生成随机运算符 - if + else + random

在掌握了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。

4.1.2.3 运算函数

运用“笨办法”学Python 3基础篇 第三部分-函数

中的设计方法,加法和减法函数功能为:

  • print 当前算式
  • 等待输入口算结果
  • 分支结构判断结果
  • print 运算结果

具体的代码为:

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。

4.1.2.4 综合

完成了随机数生成、随机运算符和运算函数后,剩下的就是综合了。综合后的代码为:

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后得到的结果为

“笨办法”学Python 3基础篇 - 数据容器与程序结构“笨办法”学Python 3基础篇系列文章前言4.1 程序逻辑结构-分支 if、elif、else4.2 程序逻辑结构-循环 for 和 while4.3 更复杂的列表操作结语

4.2 程序逻辑结构-循环 for 和 while

循环结构是另一种常用的逻辑控制结构。常用到的是for和while。

4.2.1 for + 列表

在开始使用for循环之前,我们需要在某个位置存放循环的结果,也就是需要一个数据的容器。最好的方法是使用列表。列表的定义非常简单,以 [ 开头打开列表,然后写下要放入列表的东西,用逗号隔开,就跟函数的参数一样,最后需要用右括号 ] 表明列表结束。例如:

  • hairs = [‘brown’, ‘blond’, ‘red’]

如果想要遍历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运行结果如图所示。

“笨办法”学Python 3基础篇 - 数据容器与程序结构“笨办法”学Python 3基础篇系列文章前言4.1 程序逻辑结构-分支 if、elif、else4.2 程序逻辑结构-循环 for 和 while4.3 更复杂的列表操作结语

4.2.2 while + 列表

如果要使用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运行结果为:

“笨办法”学Python 3基础篇 - 数据容器与程序结构“笨办法”学Python 3基础篇系列文章前言4.1 程序逻辑结构-分支 if、elif、else4.2 程序逻辑结构-循环 for 和 while4.3 更复杂的列表操作结语

4.2.3 挑战一个更复杂的口算训练器

之前我们的口算训练程序每次只能做一次运算。现在我们可以用逻辑循环结构来为口算训练程序添加如下功能:

  1. 用户可以设置每次训练的口算题数;
  2. 用循环结构重复生成随机口算式子并计分;
  3. 打印出最终正确率,并退出程序

具体的实现代码为:

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的运行结果为:

“笨办法”学Python 3基础篇 - 数据容器与程序结构“笨办法”学Python 3基础篇系列文章前言4.1 程序逻辑结构-分支 if、elif、else4.2 程序逻辑结构-循环 for 和 while4.3 更复杂的列表操作结语

4.3 更复杂的列表操作

在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)。结果为:

“笨办法”学Python 3基础篇 - 数据容器与程序结构“笨办法”学Python 3基础篇系列文章前言4.1 程序逻辑结构-分支 if、elif、else4.2 程序逻辑结构-循环 for 和 while4.3 更复杂的列表操作结语

结语

数据容器更重要的一个概念是:字典。这篇文章由于中途有事,又写了两天,没有来得及写字典。后面要加快进度,把字典放在后续总结,并多以案例来总结学到的基本编程理论,这样能更快速的消化。