一、循环语句
今天要说的不是最常用的while、for两种循环……而是while - else 循环 与 for - else 循环,或许也很少见到过这两个循环,是的,若不是在师兄的笔记中看到,我也没见过,孤陋寡闻了,今天就来学习一下吧,以备不时之需。
1.while - else 循环
结构如下:
while 布尔表达式:
代码块
else:
代码块
当while
循环正常执行完的情况下,执行else
输出,如果while
循环中执行了跳出循环的语句,比如 break
,将不执行else
代码块的内容。
2.for - else 循环
结构如下:
for 迭代变量 in 可迭代对象:
代码块
else:
代码块
当for
循环正常执行完的情况下,执行else
输出,如果for
循环中执行了跳出循环的语句,比如 break
,将不执行else
代码块的内容,与while - else
语句类似。
3.部分习题与解答
3-1 编写一个Python程序
来查找那些既可以被7
整除又可以被5
整除的数字,介于1500
和2700
之间。
代码如下:
for i in range(1500, 2700):
if i % 7 == 0 and i % 5 == 0:
print(i, end=' ') # 此处将每个输出元素用空格隔开
# 1505 1540 1575 1610.........2590 2625 2660 2695
3-2 龟兔赛跑游戏
题目描述:
话说这个世界上有各种各样的兔子和乌龟,但是研究发现,所有的兔子和乌龟都有一个共同的特点——喜欢赛跑。于是世界上各个角落都不断在发生着乌龟和兔子的比赛,小华对此很感兴趣,于是决定研究不同兔 子和乌龟的赛跑。他发现,兔子虽然跑比乌龟快,但它们有众所周知的毛病——骄傲且懒惰,于是在与乌龟的比赛中,一旦任一秒结束后兔子发现自己领先k
米或以上,它们就会停下来休息s
秒。对于不同兔子的k
,s
的数值是不同的,但是所有的乌龟却是一致——它们不到终点决不停止。
然而有些比赛相当漫长,全程观看会耗费大量时间,而小华发现只要在每场比赛开始后记录下兔子和乌龟的数据——兔子的速度v1
(表示每秒兔子能跑v1米),乌龟的速度v2
,以及兔子对应的k
,s
值,以及赛道的长度l
——就能预测出比赛的结果。但是小华很懒,不想通过手工计算推测出比赛的结果,于是他找到了你——一只没有感情的代码狗——请求帮助,请你写一个程序,对于输入的一场比赛的数据v1
,v2
,k
,s
,l
,就能预测该场比赛的结果。
输入:
输入只有一行,包含用空格隔开的五个正整数v1,v2,k,s,l,其中(v1,v2< =100;k< =300;s< =10;l< =10000且为v1,v2的公倍数)
输出:
输出包含两行,第一行输出比赛结果——一个大写字母“T”或“R”或“D”,分别表示乌龟获胜,兔子获胜,或者两者同时到达终点。
第二行输出一个正整数,表示获胜者(或者双方同时)到达终点所耗费的时间(秒数)。
样例输入:
10 5 5 2 20
样例输出
D
4
解题思路:
比赛的胜利 取决于 龟兔完成赛跑谁的用时更少,根据输入便能轻松的获取到 乌龟 的用时(t2 = l / v2)
,所以,若能计算出 兔子 的用时t1
, 此题不攻自破对不对?好,那就看我代码吧!我将兔子的耗时t1
主要分为两部分,一部分是休息的时间s
,一部分是奔跑的时间t
,而奔跑的时间t
里面又可分为 为了实现休息这个目标(即超越乌龟k米)在奔跑过程中而花的时间 与 还没实现这个目标就突然地~到达了终点的时间。
解题代码(向左滑动查看更多代码):
v1, v2, k, s, l = map(int, input('请逐个输入比赛数据,并用空格隔开: ').split(' '))
t1, j, t, q,= 0, 0, 0, 0, 0 # 初始化一写用到的变量,
t2 = int(l / v2) # 直接出计算出乌龟的用时
while True:
t += 1 # 计时器
if v1*t - v2*t >= ((q - j) + k): # 检查兔子是否实现了可以休息的目标,(q - j) 是龟兔实时距离
t1 += t + s # 若是,则将每次实现休息目标的耗时t与休息时间s相加,赋给记t1
j += v1*t # j 是兔子奔跑的实时总路程
q += v2*t + v2*s # q 是乌龟奔跑的实时总路程,v2*s代表在兔子休息的时间里,乌龟也要跑嘛
t = 0 # 对t置零,方便计算下一次实现休息目标的耗时
if j + v1*t == l: # 检查兔子是否到终点了
if t == 0: # 若到达终点的时刻与准备要停止休息的时刻相同
t1 -= s # 那就不用休息啦,减去原来加上的准备要休息时间
else:
t1 += t # 若到达终点的时刻与准备要停止休息的时刻不同,则加上这段还没达到休息目标就突然地到了终点的时间
break
# 以下输出模块,对耗时进行比较,并输出获胜者与其对应的耗时
if t1 < t2:
print('R')
print(t1)
elif t1 == t2:
print('D')
print(t1)
else:
print('T')
print(t2)
测试结果:
请逐个输入比赛数据,并用空格隔开: 10 5 5 2 20
D
4
请逐个输入比赛数据,并用空格隔开: 10 5 5 2 30
R
5
请逐个输入比赛数据,并用空格隔开: 50 25 150 3 5000
R
196
请逐个输入比赛数据,并用空格隔开: 6 3 8 1 18
R
3
不可否认,这段代码可读性不一定高,已尽力在对每行进行注释了… 或许将耗时作为解题的切入点,代码还可以优化,但时间紧任务重,任重而道远,就此为止吧,好吗?
以下附上我同学-----一只同样没有感情的代码狗对这道题的另一种解法(以路程为切入点),欢迎大家围观:https://blog.csdn.net/weixin_47004138/article/details/109128813
二、异常处理
1.异常是什么?
异常就是运行期检测到的错误。计算机语言针对可能出现的错误定义了异常类型,某种错误引发对应的异常时,异常处理程序将被启动,从而恢复程序的正常运行。
2.python中的异常(太多了,详细见链接)
最常见的几种:
SyntaxError:语法错误导致的异常
TypeError:不同类型间的无效操作
ValueError:传入无效的参数
KeyError:字典中查找一个不存在的关键字
参考链接:https://blog.csdn.net/weixin_45494811/article/details/104216280
3.异常处理的作用?
①异常就是可预测但是又没办法消除的一种错误。所以程序员为了在程序当中不发生这样的错误会将容易发生异常的代码用try-except
进行处理,或这通过传递由上一级进行接收并处理。如果发生异常而不去处理,会导致程序中断,也就是程序无法继续运行!
②异常处理可以让程序具有更好的容错性,是程序更加健壮。当程序运行出现意外情况的时候。系统会自动生成一个Exception
对象来通知,从而实现将“业务功能逻辑” 和“错误处理逻辑。
4.try - except
结构
try:
检测范围
except Exception[as reason]:
出现异常后的处理代码
try 语句按照如下方式工作:
- 首先,执行
try
子句(在关键字try
和关键字except
之间的语句) - 如果没有异常发生,忽略
except
子句,try
子句执行后结束。 - 如果在执行
try
子句的过程中发生了异常,那么try
子句余下的部分将被忽略。如果异常的类型和except
之后的名称相符,那么对应的except
子句将被执行。最后执行try
语句之后的代码。 - 如果一个异常没有与任何的
except
匹配,那么这个异常将会传递给上层的try
中。
5.部分习题与解答
5-1 猜数字游戏
题目描述:
电脑产生一个零到100之间的随机数字,然后让用户来猜,如果用户猜的数字比这个数字大,提示太大,否则提示太小,当用户正好猜中电脑会提示,“恭喜你猜到了这个数是…”。在用户每次猜测之前程序会输出用户是第几次猜测,如果用户输入的根本不是一个数字,程序会告诉用户"输入无效"。
(尝试使用try - except
异常处理结构对输入情况进行处理,获取随机数采用random模块)
解题代码(向左滑动查看更多代码):
import random # 导入random模块
num = random.randint(1, 101) # num 为随机产生的一个答案
i = 0
while True:
i += 1
try:
guess = int(input('这是第%d次猜,请输入一个整数哦: ' % i)) # int 搭配 input 将输入限制为整型
except ValueError:
print('输入无效,输入的是“整数”才行呢~.~')
i += 1
guess = int(input('这是第%d次猜,这次一定输入一个整数哦: ' % i))
if guess < num:
print('小了小了~~')
if guess == num:
print('猜得真他妈准!游戏结束啦~')
break
if guess > num:
print('大了大了~~')
测试结果:
这是第1次猜,请输入一个整数哦: 20
大了大了~~
这是第2次猜,请输入一个整数哦: 10
小了小了~~
这是第3次猜,请输入一个整数哦: h # 故意输入一个非整型数据
输入无效,输入的是“整数”才行呢~.~ # 此处引发异常处理结构
这是第4次猜,这次一定输入一个整数哦: 15
大了大了~~
这是第5次猜,请输入一个整数哦: 13
猜得真他妈准!游戏结束啦~
三、列表
1.关于列表,大家对它的一些常规操作,如添加、删除、排列元素都再熟悉不过了,在这里就提一下,这两天我学习到了一些比较关键又容易忽略的点吧
①append
与 extend
的区别是什么?
1)list.append(obj)
在列表末尾添加新的对象,只接受一个参数(注意是一个!),参数可以是任何数据类型,被追加的元素在 list 中保持着原结构类型,如这个元素如果也是一个 list,那么这个 list 将作为一个整体进行追加。
2) list.extend(seq)
在列表末尾一次性追加另一个序列中的多个值(注意,是多个元素! 用新列表扩展原来的列表)
例子分别如下(向左滑动查看更多代码):
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
x.append(['Thursday', 'Sunday'])
print(x)
# ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', ['Thursday', 'Sunday']] # ['Thursday', 'Sunday'] 被视为一个元素加入列表中
print(len(x)) # 6
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
x.extend(['Thursday', 'Sunday'])
print(x)
# ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Thursday', 'Sunday'] # ['Thursday', 'Sunday'] 被视为 'Thursday', 'Sunday' 两个元素加入原列表中
print(len(x)) # 7
仔细观察,能发现两个列表的长度是不一样,所以严格来说 append
是追加,把一个东西整体添加在列表后,而 extend
是扩展,把一个东西里的所有元素添加在列表后。
② 关于列表复制 的浅拷贝?深拷贝?
真正的复制是用切片的形式操作的!
见例子:
list1 = [123, 456, 789, 213]
list2 = list1 # 浅拷贝, 创建一个新的名称指向原来的地址
list3 = list1[:] # 深拷贝, 真正的开辟一片新的地址存放同样的内容,并使用新的名称
print(list2) # [123, 456, 789, 213]
print(list3) # [123, 456, 789, 213]
list1.sort() # 对列表中的元素进行按首字母小到大排列
print(list2) # [123, 213, 456, 789] # 可见,浅拷贝的list2 也跟着list1 变化
print(list3) # [123, 456, 789, 213] # 深拷贝的list3不为所动
2.部分习题与解答
2-1 列表操作练习
列表lst 内容如下
lst = [2, 5, 6, 7, 8, 9, 2, 9, 9]
请写程序完成下列操作:
- 在列表的末尾增加元素15
- 在列表的中间位置插入元素20
- 将列表[2, 5, 6]合并到lst中
- 移除列表中索引为3的元素
- 翻转列表里的所有元素
- 对列表里的元素进行排序,从小到大一次,从大到小一次
解题代码:
lst = [2, 5, 6, 7, 8, 9, 2, 9, 9]
lst.append(15) # [2, 5, 6, 7, 8, 9, 2, 9, 9, 15]
lst.insert(6, 20) # [2, 5, 6, 7, 8, 9, 20, 2, 9, 9, 15]
lst.extend([2, 5, 6]) # [2, 5, 6, 7, 8, 9, 20, 2, 9, 9, 15, 2, 5, 6]
lst.pop(3)
print(lst) # [2, 5, 6, 8, 9, 20, 2, 9, 9, 15, 2, 5, 6]
print(lst[::-1]) # [6, 5, 2, 15, 9, 9, 2, 20, 9, 8, 6, 5, 2]
lst.sort()
print(lst) # [2, 2, 2, 5, 5, 6, 6, 8, 9, 9, 9, 15, 20]
lst.sort(reverse=True)
print(lst) # [20, 15, 9, 9, 9, 8, 6, 6, 5, 5, 2, 2, 2]
2-2 修改列表
问题描述:
lst = [1, [4, 6], True]
请将列表里所有数字修改成原来的两倍
解题代码:
lst = [1, [4, 6], True]
lst[0] = 2 # 直接使用了索引,对指定的元素进行修改,简单粗暴
lst[1][0] = 8
lst[1][1] = 12
print(lst) # [2, [8, 12], True]
2-3 山脉数组的峰顶索引
现在,给定一个山脉数组,求顶峰索引。
代码如下:
(其实,我严重怀疑这道题出得不对劲,或许是我没读懂题目吧,没办法还得做一下, 哈哈)
class Solution: # 创建类
def peakIndexInMountainArray(self, A): # 定义方法,注意这里 A 是一个数组
inx = A.index(max(A)) # 直接使用 max 函数找到列表中的最大值, 再用 index 函数传回索引值
return inx
List = [1, 2, 3, 4, 2, 1, 0]
num = Solution().peakIndexInMountainArray(List)
print(num) # 即峰顶 4 的索引值为 3