外观
第6周:第三次上机课
一、简单计算器:类型和条件
本题 154 次未通过,是 py3 中最多的一题。
1. 重复读入:转换时又调用 input
错误写法:
python
a, b, op = input().split()
a = int(input())
b = int(input())为什么错: 输入只有一行 3 2 +,第一行代码已经读完。第二次 input() 会等待新的一行;OJ 输入已结束时会报 EOFError,不会自动取出刚才的 a。
怎么改: 直接写 a = int(a)、b = int(b),转换已经读到的变量。
2. 类型错误:把字符串当成整数
错误写法(这里只看除法分支):
python
a, b, op = input().split()
if op == "/":
if b == 0:
print("Divided by zero!")
else:
print(int(a) // int(b))为什么错: 输入 3 0 / 时,b 是字符串 "0",与整数 0 不相等。程序进入 else,直到做除法才转换类型,于是发生 ZeroDivisionError。
怎么改: 在 split() 后立刻执行 a = int(a)、b = int(b),再进入条件判断。类型转换要在判断之前。
3. 条件错误:or 后省略了比较
错误写法:
python
a, b, op = input().split()
if op == "+" or "-" or "*" or "/":
print("合法")
else:
print("Invalid operator!")为什么错: 输入 3 2 ? 仍输出“合法”。Python 把条件理解成 (op == "+") or "-" or "*" or "/",非空字符串 "-" 为真,后面的 else 永远进不去。
怎么改: 写 if op in ["+", "-", "*", "/"]:,或 if op == "+" or op == "-" or op == "*" or op == "/":。
二、三角形与输出:退出和空格
直角三角形题 139 次未通过,其中 49 次格式错误;数字三角形也有 58 次格式错误。
1. 直角三角形:输出结束提示,却没有退出
错误写法:
python
while True:
a, b, c = map(int, input().split())
if a == b == c == 0:
print("program finished")为什么错: 输入 0 0 0 后虽然打印了提示,while True 仍继续执行,下一轮又读取输入;没有下一行时会报 EOFError。
怎么改: 在提示后的同一级缩进加 break。全零判断放在几何判断之前,普通输入则继续循环。
2. 直角三角形:提示语少了空格
错误写法:
python
area = 6.0
print(f"{area:.1f},please input again")为什么错: 输出是 6.0,please input again,逗号后少了题目要求的空格,数值正确也会格式错误。
怎么改: 写 print(f"{area:.1f}, please input again"),固定提示语逐字符对照题面。
3. 数字三角形:行首空格数量不对
错误写法 A:把空字符串当空格。
python
n, i = 3, 1
prefix = "" * (n - i)
print(prefix + "1")为什么错: "" 里没有字符,重复两次仍为空,实际输出 "1",而不是带两个行首空格的 " 1"。改法: 用 " " * (n - i)。
错误写法 B:print 又多插入了一个空格。
python
prefix = " " * 2
numbers = "1"
print(prefix, numbers)为什么错: 两个参数之间默认插入一个空格,行首变成三个空格。改法: 用 print(prefix + numbers) 或 print(prefix, numbers, sep="");数字之间也不能额外加空格。
三、子串位置:找到后怎么继续
本题 90 次未通过。
1. 起点更新错误:没有跳过完整子串
错误写法 A:只向后移动一位。
python
text, target = "aaaa", "aa"
position = text.find(target)
while position != -1:
print(position)
position = text.find(target, position + 1)为什么错: 依次找到 0、1、2,位置 1 与前一次匹配重叠。这里只观察查找顺序,题目要求的不重叠位置是 0、2。改法: 从 position + len(target) 继续查找。
错误写法 B:从旧起点累加长度。
python
text, target = "xxabxxab", "ab"
start = 0
position = text.find(target, start) # 找到位置 2
start += len(target)
print(text.find(target, start))为什么错: start 从 0 变成 2,下一次又找到同一个位置 2。改法: 用 start = position + len(target),从 4 开始找,下一处才是 6。
2. 查找判断错误:把位置 0 当作没找到
错误写法:
python
position = "abc".find("ab")
if position:
print(position)
else:
print("no")为什么错: 找到的位置是 0,但 0 在条件中为假,所以输出了 no。反过来,没找到时返回的 -1 却会被当作真。
怎么改: 判断 if position != -1:,不能用位置的真假代替“是否找到”。
3. 多组数据错误:沿用了上一组的状态
错误写法(两组都只有一处匹配):
python
start = 0
positions = []
for text in ["xxaa", "aa"]:
position = text.find("aa", start)
if position != -1:
positions.append(position)
start = position + 2
print(*positions)为什么错: 第一组结束时 start 是 4,列表里有 2。第二组从 4 开始,漏掉应找到的 0,还把旧结果 2 再打印一次。
怎么改: 把 start = 0、positions = [] 放到外层 for 的内部,每组开始重新初始化。
4. 输出格式错误:直接打印列表,或漏掉换行
错误写法 A:直接输出列表。
python
positions = [0, 2]
print(positions)为什么错: 输出 [0, 2],题目要的是 0 2。改法: 有匹配时用 print(*positions);没有匹配时单独输出 no。
错误写法 B:每组输出后不换行。
python
for positions in [[0, 2], [1]]:
for pos in positions:
print(pos, end=" ")为什么错: 两组挤在同一行,变成 0 2 1 。改法: 每次内层循环结束后补 print(),与内层 for 对齐。
四、邮资:整除边界与独立条件
本题 82 次未通过。只讲两个问题。
1. 档数错误:整除后无条件加一
错误写法:
python
weight = 1500
extra = weight - 1000
blocks = extra // 500 + 1
print(8 + blocks * 4)为什么错: 超出 500 克,恰好一档,500 // 500 + 1 却算成两档,输出 16,正确邮费应为 12。
怎么改: 只在超重时计算档数;有余数才加一,或先 import math,再用 math.ceil(extra / 500)。
2. 分支错误:把超重和加急写成 if / elif
错误写法:
python
weight, urgent = 1200, "y"
fee, extra_fee = 8, 4
if weight > 1000:
fee += extra_fee
elif urgent == "y":
fee += 5
print(fee)为什么错: 超重条件成立后,整个 if / elif 只执行第一支,漏收加急费,输出 12,应该是 17。
怎么改: 把 elif 改为独立的 if。超重与加急可以同时发生,两笔费用都要检查。
五、py4:函数先会用 return
数列求和、删除子串、凯撒密码要求使用函数。
1. 参数与返回值:把数据传进去,把结果拿回来
函数内算结果,主程序读入、调用、输出:
python
def square(x):
return x * x
answer = square(3)
print(answer) # 92. print 与 return:显示结果不等于返回结果
错误写法:
python
def square(x):
print(x * x)
answer = square(3)
print(answer)为什么错: 先打印 9,随后又打印 None。函数内的 print 只负责显示,没有 return 时调用者得到 None。
怎么改: 把函数内的 print(x * x) 改为 return x * x,由主程序负责输出。
3. return 的位置:算完之后再返回
错误写法(用普通求和观察执行顺序):
python
def total(numbers):
result = 0
for number in numbers:
result += number
return result
print(total([1, 2, 3]))为什么错: 输出 1,后面的 2、3 根本没处理。return 会立即结束整个函数。
怎么改: 将 return result 向左退一层,与 for 对齐。本周数列求和也要加完所有项再返回。
六、py4:各题注意事项
1. 数列求和
易错写法:把 0 也放进分母序列。
python
n = 2
result = 0
for denominator in range(n, -1, -2):
result += 1 / denominator为什么错: 分母依次是 2、0,第二轮发生除零异常。改法: 用 range(n, 0, -2),保持与 n 同奇偶,并排除 0。
输出提醒: 固定显示 6 位小数,用 f"{result:.6f}"。print(round(0.5, 6)) 只显示 0.5,round 不负责补零。
2. 删除子串
易错写法:把模式直接当作替换次数。
python
text, target = "aaaa", "aa"
mode = 0
print(text.replace(target, "", mode))为什么错: replace 的第三个参数是次数,0 表示一次也不删,输出仍是 aaaa;题目的模式 0 却要求删一次,应该剩 aa。
改法: 模式 0 时指定次数 1;模式 1 时省略次数参数,删掉全部不重叠匹配。
不重叠提醒: aababa 删除 aba 得到 aba,不再删除拼接后新形成的子串。
3. 机器猜数
易错写法:中点向下取整。
python
left, right = 1, 100
guess = (left + right) // 2
print(guess)为什么错: 输出 50,题目要求向上取整,第一次应猜 51。改法: 用 (left + right + 1) // 2。
计数提醒: 范围只剩一个数时已经确定答案,不再计一次;循环条件应为 left < right,不能把相等时也算作一次猜测。
4. 自动判题
易错写法:直接比较未舍入的计算值。
python
value = 1 / 3
answer = 0.33
print(value == answer)为什么错: 1/3 的计算值不是 0.33,比较结果为 False;题目要求保留两位后比较,这组应为 true。改法: 比较 round(value, 2) 与 answer。
- 输入: 先拆等号,再处理左侧表达式。
- 输出: 使用字符串
"true"/"false";直接打印 Python 的布尔值会使首字母大写。
5. 凯撒密码
易错写法:数字也按 26 循环。
python
ch, key = "9", 1
position = ord(ch) - ord("0")
print(chr(ord("0") + (position + key) % 26))为什么错: 数字只有 10 个,9 再前进一位应回到 0;模 26 得到位置 10,输出的是冒号 :。改法: 数字模 10,字母模 26。
- 解密方向: 要反向移动,不能继续加密钥。
- 其他字符: 空格、标点原样保留,不能用 split 后重新拼接来读取消息。