跳转至

程序改错题解析

第1题:温度转换

题目: 将输入的摄氏温度转换为华氏温度并输出。转换公式:F = C * 9 / 5 + 32。

Python
1
2
3
4
5
6
7
8
9
#**********begin1**********
c = input("请输入摄氏温度:")                    # ❌ 错误1
#**********end1**********
#**********begin2**********
f = c * 9 // 5 + 32                             # ❌ 错误2
#**********end2**********
#**********begin3**********
print("华氏温度为:" + f)                        # ❌ 错误3
#**********end3**********

✅ 错误修正

错误位置 原代码 修正后 错误原因
begin1 c = input("请输入摄氏温度:") c = int(input("请输入摄氏温度:")) input() 返回字符串,需要转为整数
begin2 f = c * 9 // 5 + 32 f = c * 9 / 5 + 32 // 是整除,会丢失小数部分,应用 / 精确除法
begin3 print("华氏温度为:" + f) print(f"华氏温度为:{f}")print("华氏温度为:" + str(f)) f 是浮点数,不能与字符串直接拼接

完整正确代码

Python
1
2
3
4
5
6
c = int(input("请输入摄氏温度:"))            # ✅ 修正1:int() 转为整数
f = c * 9 / 5 + 32                           # ✅ 修正2:/ 精确除法
print(f"华氏温度为:{f}")                     # ✅ 修正3:f-string 格式化输出

# 输入 25 时,输出: 华氏温度为:77.0
# 输入 37 时,输出: 华氏温度为:98.6

解析:

  • 错误1input() 函数返回的是字符串类型。如果输入 25c 的值是 "25"(字符串),不是 25(整数)。需要用 int() 将字符串转为整数,否则后续运算会出错(字符串乘整数是重复操作)

    Python
    1
    2
    3
    c = input("请输入:")   # 输入 25 → c = "25"(字符串)
    c * 9                   # "25" * 9 = "25252525252525252525"(字符串重复!)
    int(c) * 9              # 25 * 9 = 225(数值运算 ✅)
    
  • 错误2// 是整除运算符,只保留整数部分。例如 225 // 5 = 45,而 225 / 5 = 45.0。当结果不能整除时会丢失精度,如 37 * 9 // 5 = 66(实际应为 66.6)。温度转换应使用 / 保证精度

  • 错误3f 是浮点数(float),Python 不允许字符串与浮点数直接用 + 拼接,会报 TypeError。解决方案:

    • f-string:f"华氏温度为:{f}"(推荐)
    • str() 转换:"华氏温度为:" + str(f)

🔑 知识点:输入输出与类型转换

  • input() 返回字符串,数值运算前必须转换:
转换函数 用途 示例
int() 转整数 int("25")25
float() 转浮点数 float("3.14")3.14
str() 转字符串 str(25)"25"
  • 除法运算符区别:
运算符 含义 示例
/ 精确除法 7 / 23.5
// 整除(向下取整) 7 // 23
% 取余 7 % 21
  • 字符串与数值拼接方式:
    • f-string:f"值:{x}"(推荐)
    • str() 转换:"值:" + str(x)
    • print 多参数:print("值:", x)
📖 拓展
Python
# 更完善的温度转换程序
c = float(input("请输入摄氏温度:"))   # float 支持小数输入
f = c * 9 / 5 + 32
print(f"摄氏 {c}°C = 华氏 {f:.1f}°F")  # .1f 保留1位小数

# 反向转换:华氏转摄氏
f = float(input("请输入华氏温度:"))
c = (f - 32) * 5 / 9
print(f"华氏 {f}°F = 摄氏 {c:.1f}°C")

# 常见温度对照
# 0°C  = 32°F   (冰点)
# 100°C = 212°F (沸点)
# 37°C  = 98.6°F(体温)

📌 记忆要点

  • input() 返回字符串,数值运算前用 int()float() 转换

  • / 是精确除法,// 是整除,温度转换用 /

  • 数值不能直接与字符串 + 拼接,用 f-string 或 str() 转换


第2题:列表最大值

题目: 遍历列表,找出并输出其中的最大值。

Python
nums = [23, 45, 12, 67, 34]
max_num = nums[0]
for num in nums:
    #**********begin1**********
    if num < max_num                          # ❌ 错误1
    #**********end1**********
        #**********begin2**********
        max_num == num                        # ❌ 错误2
        #**********end2**********
print(f"最大值:{max_num}")

✅ 错误修正

错误位置 原代码 修正后 错误原因
begin1 if num < max_num if num > max_num 求最大值应在当前元素更大时更新,比较方向反了
begin2 max_num == num max_num = num == 是比较运算符,= 才是赋值运算符

完整正确代码

Python
1
2
3
4
5
6
7
8
nums = [23, 45, 12, 67, 34]
max_num = nums[0]
for num in nums:
    if num > max_num:                     # ✅ 修正1:大于才更新
        max_num = num                     # ✅ 修正2:赋值用 = 不是 ==
print(f"最大值:{max_num}")

# 输出: 最大值:67

解析:

  • 错误1num < max_num 表示"当前元素比最大值小",此时更新最大值毫无意义——应该更新的是当遇到更大的元素时。求最大值的逻辑是:当 num > max_num(当前元素更大)时,才更新 max_num

    Python
    1
    2
    3
    4
    5
    6
    7
    # 错误逻辑:遇到比最大值还小的才更新
    # 结果:max_num 永远不会变大(初始值就是第一个元素)
    # 实际效果:max_num 始终为 nums[0] = 23
    
    # 正确逻辑:遇到比最大值更大的才更新
    if num > max_num:
        max_num = num
    
  • 错误2== 是比较运算符,返回 TrueFalse,不会修改变量的值。max_num == num 只是比较两者是否相等,结果被丢弃。正确写法是 max_num = num,用 = 赋值

    Python
    max_num == num   # 比较:返回 True/False,max_num 不变
    max_num = num    # 赋值:将 num 的值存入 max_num ✅
    

🔑 知识点:赋值与比较

  • === 的区别:
运算符 含义 用途 示例
= 赋值 将右边的值存入左边的变量 x = 5(x 变为 5)
== 比较 判断两边的值是否相等 x == 5(返回 True/False)
  • 求最值的通用模式:
Python
# 求最大值
max_val = lst[0]
for item in lst:
    if item > max_val:    # 遇到更大的
        max_val = item    # 更新最大值

# 求最小值
min_val = lst[0]
for item in lst:
    if item < min_val:    # 遇到更小的
        min_val = item    # 更新最小值
📖 拓展
Python
# 方法2:使用内置函数
nums = [23, 45, 12, 67, 34]
print(max(nums))  # 67
print(min(nums))  # 12

# 方法3:使用排序
nums_sorted = sorted(nums)
print(nums_sorted[-1])  # 最大值:67
print(nums_sorted[0])   # 最小值:12

# 方法4:同时求最大值和最小值
def find_max_min(lst):
    max_val = min_val = lst[0]
    for item in lst:
        if item > max_val:
            max_val = item
        if item < min_val:
            min_val = item
    return max_val, min_val

maximum, minimum = find_max_min([23, 45, 12, 67, 34])
print(f"最大值:{maximum},最小值:{minimum}")

📌 记忆要点

  • 求最大值用 > 比较,求最小值用 < 比较

  • 赋值用 =,比较用 ==,不要混淆

  • 初始值设为列表第一个元素 lst[0],不要设为 0(负数列表会出错)


第3题:文件写入

题目: 将文本内容写入文件 output.txt。

Python
#**********begin1**********
f = open("output.txt", "r")                  # ❌ 错误1
#**********end1**********
#**********begin2**********
f.writeline("Hello, World!\n")               # ❌ 错误2
#**********end2**********
f.writelines(["Line 1\n", "Line 2\n"])
#**********begin3**********
f.close                                       # ❌ 错误3
#**********end3**********

✅ 错误修正

错误位置 原代码 修正后 错误原因
begin1 open("output.txt", "r") open("output.txt", "w") "r" 是只读模式,无法写入;写入文件应使用 "w" 模式
begin2 f.writeline(...) f.write(...) 文件对象没有 writeline 方法,正确的方法是 write
begin3 f.close f.close() close 是方法,必须加括号 () 才能调用

完整正确代码

Python
1
2
3
4
5
6
7
8
9
f = open("output.txt", "w")               # ✅ 修正1:写入模式 "w"
f.write("Hello, World!\n")                # ✅ 修正2:write 方法
f.writelines(["Line 1\n", "Line 2\n"])
f.close()                                  # ✅ 修正3:调用 close() 方法

# output.txt 内容:
# Hello, World!
# Line 1
# Line 2

解析:

  • 错误1"r" 是只读模式(read),尝试写入会报 UnsupportedOperation 错误。写入文件应使用 "w" 模式(write)。如果文件不存在,"w" 模式会自动创建;如果文件已存在,"w" 模式会覆盖原内容

    Python
    1
    2
    3
    4
    open("file.txt", "r")   # 只读,不可写入
    open("file.txt", "w")   # 只写,覆盖已有内容
    open("file.txt", "a")   # 追加,在文件末尾添加
    open("file.txt", "r+")  # 读写
    
  • 错误2:文件对象没有 writeline 方法。正确的方法是 write(),用于写入单个字符串。注意 writelines() 是另一个方法,用于写入字符串列表,但它不会自动添加换行符

    Python
    1
    2
    3
    f.write("Hello\n")              # 写入单个字符串 ✅
    f.writelines(["A\n", "B\n"])    # 写入字符串列表 ✅
    f.writeline("Hello\n")          # ❌ 不存在此方法!
    
  • 错误3f.close 只是引用了 close 方法对象,并没有调用它。必须加 () 才能执行关闭操作:f.close()。不加括号的话文件不会被关闭,可能导致数据丢失

    Python
    f.close     # 只是一个方法对象的引用,不会关闭文件
    f.close()   # 调用方法,关闭文件 ✅
    

🔑 知识点:文件操作

  • 文件打开模式:
模式 含义 文件存在时 文件不存在时
"r" 只读 读取内容 报错 FileNotFoundError
"w" 只写 覆盖内容 创建新文件
"a" 追加 末尾添加 创建新文件
"r+" 读写 读取+写入 报错
  • 文件写入方法:
方法 参数 说明
write(s) 字符串 写入单个字符串
writelines(lst) 字符串列表 写入多个字符串,不自动换行
  • 推荐使用 with 语句自动管理文件关闭:
Python
1
2
3
4
with open("output.txt", "w") as f:
    f.write("Hello, World!\n")
    f.writelines(["Line 1\n", "Line 2\n"])
# 离开 with 块后文件自动关闭,无需手动调用 close()
📖 拓展
Python
# 方法1:手动打开和关闭
f = open("output.txt", "w")
f.write("Hello, World!\n")
f.close()

# 方法2:with 语句(推荐,自动关闭)
with open("output.txt", "w") as f:
    f.write("Hello, World!\n")
    f.writelines(["Line 1\n", "Line 2\n"])

# 方法3:追加模式
with open("output.txt", "a") as f:
    f.write("Line 3\n")  # 在文件末尾追加

# 方法4:读取文件内容
with open("output.txt", "r") as f:
    content = f.read()       # 读取全部内容
    # lines = f.readlines()  # 按行读取为列表
print(content)

📌 记忆要点

  • 写文件用 "w" 模式,读文件用 "r" 模式,追加用 "a" 模式

  • 写入方法:write() 写单个字符串,writelines() 写字符串列表

  • 方法调用必须加括号:f.close() 不是 f.close

  • 推荐使用 with open(...) as f: 自动管理文件


第4题:素数判断

题目: 判断输入的正整数是否为素数,并输出结果。

Python
def is_prime(n):
    if n < 2:
        return False
    #**********begin1**********
    for i in range(1, n):                     # ❌ 错误1
    #**********end1**********
        #**********begin2**********
        if n / i == 0:                        # ❌ 错误2
        #**********end2**********
            return False
    return True

num = int(input("请输入一个正整数:"))
#**********begin3**********
if is_prime num:                              # ❌ 错误3
#**********end3**********
    print(f"{num}是素数")
else:
    print(f"{num}不是素数")

✅ 错误修正

错误位置 原代码 修正后 错误原因
begin1 range(1, n) range(2, n) 从1开始会使 n%1==0 恒成立,所有数都被判为非素数
begin2 n / i == 0 n % i == 0 判断整除应用取余 %,除法 / 永远不会等于0(n > i时)
begin3 is_prime num is_prime(num) 函数调用必须加括号包裹参数

完整正确代码

Python
def is_prime(n):
    if n < 2:
        return False
    for i in range(2, n):                 # ✅ 修正1:从2开始
        if n % i == 0:                    # ✅ 修正2:取余判断整除
            return False
    return True

num = int(input("请输入一个正整数:"))
if is_prime(num):                         # ✅ 修正3:函数调用加括号
    print(f"{num}是素数")
else:
    print(f"{num}不是素数")

# 输入 7  → 输出: 7是素数
# 输入 10 → 输出: 10不是素数
# 输入 1  → 输出: 1不是素数

解析:

  • 错误1range(1, n) 从 1 开始,而任何整数都能被 1 整除(n % 1 == 0 恒成立),这会导致所有数都被判为非素数。素数判断应从 2 开始试除:range(2, n)

    Python
    # range(1, n) 的遍历过程(以 n=7 为例):
    # i=1: 7 % 1 == 0 → True → return False(错误!1能整除所有数)
    
    # range(2, n) 的遍历过程:
    # i=2: 7 % 2 == 1 → 不整除
    # i=3: 7 % 3 == 1 → 不整除
    # i=4: 7 % 4 == 3 → 不整除
    # i=5: 7 % 5 == 2 → 不整除
    # i=6: 7 % 6 == 1 → 不整除
    # 循环结束 → return True(7是素数 ✅)
    
  • 错误2n / i 是除法运算,结果是一个浮点数,几乎永远不会恰好等于 0。判断能否整除应该用取余运算 %:如果 n % i == 0,说明 n 能被 i 整除,n 不是素数

    Python
    1
    2
    3
    4
    7 / 2   # 3.5,不等于0
    7 % 2   # 1,不等于0 → 不能整除 ✅
    10 / 2  # 5.0,不等于0
    10 % 2  # 0,等于0 → 能整除 ✅
    
  • 错误3:Python 中函数调用必须用括号包裹参数。is_prime num 是语法错误,正确写法是 is_prime(num)

🔑 知识点:素数判断与运算符

  • 素数定义:大于 1 且只能被 1 和自身整除的正整数

  • 判断素数的标准流程:

    1. n < 2 → 不是素数
    2. 遍历 2 到 n-1,检查是否有整除
    3. 有整除 → 不是素数;全部不能整除 → 是素数
  • /% 的区别:

运算符 含义 示例 结果
/ 除法 7 / 2 3.5
// 整除 7 // 2 3
% 取余 7 % 2 1
  • 判断整除:a % b == 0(a 能被 b 整除)
📖 拓展
Python
# 优化版:只需检查到 √n
import math
def is_prime_optimized(n):
    if n < 2:
        return False
    for i in range(2, int(math.sqrt(n)) + 1):
        if n % i == 0:
            return False
    return True

# 为什么只需检查到 √n?
# 如果 n = a * b,且 a ≤ b,则 a ≤ √n
# 所以如果 n 有因子,一定有一个 ≤ √n

# 性能对比(判断 1000003 是否为素数):
# range(2, n)     → 循环约 100 万次
# range(2, √n+1)  → 循环约 1000 次

# 找出 1~100 的所有素数
primes = [n for n in range(2, 101) if is_prime_optimized(n)]
print(primes)
# [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
#  53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

📌 记忆要点

  • 素数判断循环从 2 开始:range(2, n),不是 range(1, n)

  • 判断整除用 %(取余),不是 /(除法)

  • 函数调用必须加括号:func(arg),不是 func arg


第5题:字符统计

题目: 统计字符串中大写字母、小写字母和数字的个数。

Python
s = "Hello World 123!"
upper_count = 0
lower_count = 0
digit_count = 0
for ch in s:
    #**********begin1**********
    if ch.isupper                               # ❌ 错误1
        upper_count += 1
    elif ch.islower():
        lower_count += 1
    elif ch.isdigit():
        digit_count += 1
    #**********end1**********
#**********begin2**********
print("大写字母:" + upper_count + "个,小写字母:" + lower_count + "个,数字:" + digit_count + "个")
#**********end2**********

✅ 错误修正

错误位置 原代码 修正后 错误原因
begin1 ch.isupper ch.isupper() isupper 是方法,必须加 () 调用;不加括号是方法对象引用,在 if 中恒为 True
begin2 "大写字母:" + upper_count + "个" f"大写字母:{upper_count}个...""大写字母:" + str(upper_count) + "个" upper_count 等是整数,不能与字符串直接拼接

完整正确代码

Python
s = "Hello World 123!"
upper_count = 0
lower_count = 0
digit_count = 0
for ch in s:
    if ch.isupper():                       # ✅ 修正1:加括号调用方法
        upper_count += 1
    elif ch.islower():
        lower_count += 1
    elif ch.isdigit():
        digit_count += 1
print(f"大写字母:{upper_count}个,小写字母:{lower_count}个,数字:{digit_count}个")
                                           # ✅ 修正2:使用 f-string

# 输出: 大写字母:2个,小写字母:8个,数字:3个

解析:

  • 错误1ch.isupper(无括号)是方法对象的引用,不是方法调用。在 if 条件中,方法对象被视为"真值"(truthy),导致条件永远为 True。所有字符都会被判定为大写字母,统计结果错误

    Python
    1
    2
    3
    4
    "H".isupper    # <built-in method isupper of str object>(方法对象,truthy)
    "H".isupper()  # True(方法调用,返回布尔值 ✅)
    "h".isupper    # <built-in method isupper of str object>(同样是方法对象,truthy!)
    "h".isupper()  # False(方法调用,返回正确结果 ✅)
    

    加上 if ch.isupper: 后,所有字符(包括小写字母、数字、空格)都会被判定为"大写",因为方法对象本身是 truthy 的

  • 错误2upper_countlower_countdigit_count 都是整数,Python 不允许整数与字符串用 + 拼接。解决方案:

    • f-string:f"大写字母:{upper_count}个"(推荐,简洁清晰)
    • str() 转换:"大写字母:" + str(upper_count) + "个"

🔑 知识点:字符串判断方法

  • 常用字符串判断方法(注意加括号调用):
方法 功能 示例
isupper() 是否全为大写 "ABC".isupper()True
islower() 是否全为小写 "abc".islower()True
isdigit() 是否全为数字 "123".isdigit()True
isalpha() 是否全为字母 "abc".isalpha()True
isalnum() 是否为字母或数字 "abc123".isalnum()True
isspace() 是否为空白字符 " ".isspace()True
  • 方法调用必须加括号:
    • ch.isupper → 方法对象(truthy,始终为 True)
    • ch.isupper() → 方法调用(返回 True/False)
📖 拓展
Python
# 方法2:使用字符串方法配合 sum()
s = "Hello World 123!"
upper_count = sum(1 for ch in s if ch.isupper())
lower_count = sum(1 for ch in s if ch.islower())
digit_count = sum(1 for ch in s if ch.isdigit())
print(f"大写:{upper_count},小写:{lower_count},数字:{digit_count}")

# 方法3:ASCII 码判断(不推荐,可读性差)
for ch in s:
    if 65 <= ord(ch) <= 90:     # A-Z
        upper_count += 1
    elif 97 <= ord(ch) <= 122:  # a-z
        lower_count += 1
    elif 48 <= ord(ch) <= 57:   # 0-9
        digit_count += 1

# 方法4:统计所有字符类型
s = "Hello World 123!"
for ch in s:
    if ch.isupper():
        print(f"'{ch}' → 大写字母")
    elif ch.islower():
        print(f"'{ch}' → 小写字母")
    elif ch.isdigit():
        print(f"'{ch}' → 数字")
    else:
        print(f"'{ch}' → 其他字符")

📌 记忆要点

  • 字符串判断方法必须加 () 调用:ch.isupper() 不是 ch.isupper

  • 不加括号得到的是方法对象,在 if 中恒为 True

  • 整数与字符串拼接用 f-string:f"数量:{count}"


第6题:斐波那契数列

题目: 生成前n个斐波那契数并存入列表返回。

Python
def fibonacci(n):
    if n <= 0:
        return []
    if n == 1:
        return [1]
    fib = [1, 1]
    #**********begin1**********
    for i in range(2, n - 1):                  # ❌ 错误1
    #**********end1**********
        #**********begin2**********
        fib.add(fib[i-1] + fib[i-2])           # ❌ 错误2
        #**********end2**********
    return fib

#**********begin3**********
result = fibonacci 10                          # ❌ 错误3
#**********end3**********
print(result)

✅ 错误修正

错误位置 原代码 修正后 错误原因
begin1 range(2, n - 1) range(2, n) n-1 少生成了一个数,列表只有 n-1 个元素,应为 n 个
begin2 fib.add(...) fib.append(...) 列表没有 add 方法,添加元素应使用 append
begin3 fibonacci 10 fibonacci(10) 函数调用必须用括号包裹参数

完整正确代码

Python
def fibonacci(n):
    if n <= 0:
        return []
    if n == 1:
        return [1]
    fib = [1, 1]
    for i in range(2, n):                  # ✅ 修正1:range(2, n)
        fib.append(fib[i-1] + fib[i-2])    # ✅ 修正2:append 方法
    return fib

result = fibonacci(10)                     # ✅ 修正3:函数调用加括号
print(result)

# 输出: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

解析:

  • 错误1range(2, n-1) 生成 2 到 n-2 的整数,只有 n-3 次循环。列表初始有 2 个元素 [1, 1],再添加 n-3 个,总共 n-1 个元素,但题目要求 n 个。range(2, n) 生成 2 到 n-1 的整数,循环 n-2 次,总共 2 + (n-2) = n 个元素

    Python
    1
    2
    3
    # n=10 时:
    # range(2, 9) → i = 2,3,4,5,6,7,8 → 循环7次 → 列表9个元素 ❌
    # range(2, 10) → i = 2,3,4,5,6,7,8,9 → 循环8次 → 列表10个元素 ✅
    
  • 错误2:列表(list)没有 add 方法,添加元素应使用 append 方法。add 是集合(set)的方法

    Python
    1
    2
    3
    4
    5
    6
    7
    fib = [1, 1]
    fib.append(2)   # 列表添加元素 ✅ → [1, 1, 2]
    fib.add(2)      # AttributeError: 'list' object has no attribute 'add'
    
    # set 使用 add
    s = {1, 2}
    s.add(3)        # 集合添加元素 ✅ → {1, 2, 3}
    
  • 错误3:Python 中函数调用必须用括号包裹参数。fibonacci 10 会被解释为引用 fibonacci 函数对象然后跟一个 10,这是语法错误。正确写法是 fibonacci(10)

🔑 知识点:range 与列表方法

  • range(start, stop) 的范围是 [start, stop),即包含 start,不包含 stop
代码 生成的序列 元素个数
range(2, n-1) 2, 3, ..., n-2 n-3 个
range(2, n) 2, 3, ..., n-1 n-2 个
  • 列表 vs 集合的添加方法:
类型 添加方法 示例
列表 list append(item) lst.append(3) → 末尾添加
列表 list insert(i, item) lst.insert(0, 3) → 指定位置插入
集合 set add(item) s.add(3) → 添加元素
  • 斐波那契数列:每一项等于前两项之和
    • F(1)=1, F(2)=1, F(3)=2, F(4)=3, F(5)=5, ...
📖 拓展
Python
# 方法2:生成器(节省内存)
def fib_generator(n):
    a, b = 1, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

print(list(fib_generator(10)))
# [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

# 方法3:递归(效率低,仅适合学习)
def fib_recursive(n):
    if n <= 2:
        return 1
    return fib_recursive(n-1) + fib_recursive(n-2)

# 方法4:列表推导式配合动态规划
def fib_dp(n):
    fib = [0, 1]
    for i in range(2, n + 1):
        fib.append(fib[i-1] + fib[i-2])
    return fib[1:]  # 去掉开头的 0

print(fib_dp(10))
# [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

📌 记忆要点

  • range(2, n) 包含 2,不包含 n;注意 n-1 的 off-by-one 错误

  • 列表添加用 append(),集合添加用 add(),不要混淆

  • 函数调用必须加括号:func(arg),不是 func arg


第7题:学生信息类

题目: 定义学生类,按成绩从高到低排序后输出每位学生的信息。

Python
class Student:
    #**********begin1**********
    def _init_(self, name, score):             # ❌ 错误1
    #**********end1**********
        self.name = name
        self.score = score

    def info(self):
        #**********begin2**********
        return self.name + "的成绩为:" + self.score    # ❌ 错误2
        #**********end2**********

students = [
    Student("张三", 85),
    Student("李四", 92),
    Student("王五", 78)
]
#**********begin3**********
students.sort(key=lambda s: s.score)           # ❌ 错误3
#**********end3**********
for s in students:
    print(s.info())

✅ 错误修正

错误位置 原代码 修正后 错误原因
begin1 def _init_ def __init__ 构造方法必须用双下划线 __init__,单下划线 _init_ 不是特殊方法
begin2 + self.score + str(self.score)f"..." self.score 是 int,不能与 str 直接拼接
begin3 key=lambda s: s.score key=lambda s: s.score, reverse=True 默认升序,题目要求降序需加 reverse=True

完整正确代码

Python
class Student:
    def __init__(self, name, score):       # ✅ 修正1:双下划线 __init__
        self.name = name
        self.score = score

    def info(self):
        return f"{self.name}的成绩为:{self.score}"  # ✅ 修正2:f-string

students = [
    Student("张三", 85),
    Student("李四", 92),
    Student("王五", 78)
]
students.sort(key=lambda s: s.score, reverse=True)  # ✅ 修正3:降序排序
for s in students:
    print(s.info())

# 输出:
# 李四的成绩为:92
# 张三的成绩为:85
# 王五的成绩为:78

解析:

  • 错误1_init_ 使用的是单下划线,这不是 Python 的特殊方法名。Python 的构造方法必须命名为 __init__(双下划线),在创建对象时会自动调用。使用 _init_ 不会自动调用,导致 Student("张三", 85)TypeError

    Python
    1
    2
    3
    4
    5
    6
    7
    # 单下划线:普通方法,不会自动调用
    def _init_(self, name, score):   # ❌ 创建对象时不会执行
        ...
    
    # 双下划线:构造方法,创建对象时自动调用
    def __init__(self, name, score): # ✅ 创建对象时自动执行
        ...
    
  • 错误2self.score 是整数(int),self.name 是字符串(str),Python 中 str + int 会报 TypeError。需要将 self.score 转为字符串:

    • f-string:f"{self.name}的成绩为:{self.score}"(推荐)
    • str() 转换:self.name + "的成绩为:" + str(self.score)
  • 错误3sort(key=lambda s: s.score) 默认按 score 升序排列(从低到高),输出为"王五78、张三85、李四92"。题目要求从高到低排序,需要加 reverse=True

🔑 知识点:类定义与排序

  • Python 特殊方法使用双下划线(dunder 方法):
方法 用途 调用时机
__init__ 构造方法 创建对象时
__str__ 字符串表示 print(obj) / str(obj)
__repr__ 详细表示 交互式输出 / repr(obj)
__len__ 长度 len(obj)
__lt__ 小于比较 obj1 < obj2
  • sort() / sorted() 参数:
    • key:排序依据函数
    • reverseTrue 为降序,False 为升序(默认)
Python
1
2
3
4
# 升序(默认)
students.sort(key=lambda s: s.score)
# 降序
students.sort(key=lambda s: s.score, reverse=True)
📖 拓展
Python
# 方法2:实现 __lt__ 方法,让对象可直接比较
class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score

    def __lt__(self, other):
        return self.score > other.score  # 降序:大于时返回True

    def __str__(self):
        return f"{self.name}的成绩为:{self.score}"

students = [Student("张三", 85), Student("李四", 92), Student("王五", 78)]
students.sort()  # 直接排序,无需 key 和 reverse
for s in students:
    print(s)

# 方法3:使用 __str__ 简化输出
class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score

    def __str__(self):
        return f"{self.name}的成绩为:{self.score}"

students = [Student("张三", 85), Student("李四", 92), Student("王五", 78)]
for s in sorted(students, key=lambda s: s.score, reverse=True):
    print(s)

📌 记忆要点

  • 构造方法:__init__(双下划线),不是 _init_

  • 字符串与整数拼接:用 f-string 或 str() 转换

  • 降序排序:sort(key=..., reverse=True)


第8题:最大公约数

题目: 使用辗转相除法求两个正整数的最大公约数。

Python
def gcd(a, b):
    #**********begin1**********
    while b != 0                               # ❌ 错误1
    #**********end1**********
        #**********begin2**********
        a, b = b, a / b                        # ❌ 错误2
        #**********end2**********
    return a

num1 = 48
num2 = 18
#**********begin3**********
print("最大公约数为:" + gcd(num1, num2))       # ❌ 错误3
#**********end3**********

✅ 错误修正

错误位置 原代码 修正后 错误原因
begin1 while b != 0 while b != 0: while 语句末尾缺少冒号
begin2 a / b a % b 辗转相除法用取余 %,不是除法 /
begin3 + gcd(num1, num2) + str(gcd(num1, num2)) 或 f-string gcd() 返回整数,不能与字符串直接拼接

完整正确代码

Python
def gcd(a, b):
    while b != 0:                          # ✅ 修正1:添加冒号
        a, b = b, a % b                    # ✅ 修正2:取余运算
    return a

num1 = 48
num2 = 18
print(f"最大公约数为:{gcd(num1, num2)}")   # ✅ 修正3:f-string

# 输出: 最大公约数为:6

解析:

  • 错误1while 语句末尾必须加冒号 :,否则是语法错误。Python 的复合语句(ifelifelseforwhiledefclass 等)都以冒号结尾

    Python
    while b != 0    # ❌ 缺少冒号
    while b != 0:   # ✅ 语法正确
    
  • 错误2:辗转相除法(欧几里得算法)的核心是取余运算,不是除法。a, b = b, a % b 的含义是:用 b 替换 a,用 a 除以 b 的余数替换 b,直到余数为 0

    Python
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 辗转相除法求 gcd(48, 18):
    # 第1轮:a=48, b=18 → a=18, b=48%18=12
    # 第2轮:a=18, b=12 → a=12, b=18%12=6
    # 第3轮:a=12, b=6  → a=6,  b=12%6=0
    # b=0,结束,返回 a=6
    
    # 如果用除法 a/b:
    # 第1轮:a=48, b=18 → a=18, b=48/18=2.666...
    # 结果是浮点数,永远无法等于0,死循环!
    
  • 错误3gcd(num1, num2) 返回整数 6,"最大公约数为:" + 6 会报 TypeError。需要将整数转为字符串或使用 f-string

🔑 知识点:辗转相除法

  • 辗转相除法(欧几里得算法):

    • 原理:gcd(a, b) = gcd(b, a % b),直到 b == 0,此时 a 即为最大公约数
    • 时间复杂度:O(log(min(a, b)))
  • Python 中的冒号规则:

语句 是否需要冒号
if ... 需要 :
elif ... 需要 :
else 需要 :
for ... 需要 :
while ... 需要 :
def ... 需要 :
class ... 需要 :
  • %(取余)vs /(除法):
    • 取余:48 % 18 = 12(48除以18的余数)
    • 除法:48 / 18 = 2.666...(48除以18的商)
📖 拓展
Python
# 方法2:递归实现
def gcd_recursive(a, b):
    if b == 0:
        return a
    return gcd_recursive(b, a % b)

# 方法3:使用 math.gcd(Python 内置)
import math
print(math.gcd(48, 18))  # 6

# 扩展:求最小公倍数 LCM
def lcm(a, b):
    return a * b // gcd(a, b)

print(f"GCD: {gcd(48, 18)}")  # GCD: 6
print(f"LCM: {lcm(48, 18)}")  # LCM: 144

# 关系:GCD * LCM = a * b
# 验证:6 * 144 = 864 = 48 * 18 ✅

# 扩展:求多个数的 GCD
from functools import reduce
nums = [12, 18, 24]
print(reduce(gcd, nums))  # 6

📌 记忆要点

  • whileiffordef 等语句末尾必须加冒号 :

  • 辗转相除法用取余 %,不是除法 /

  • 整数与字符串拼接用 f-string 或 str() 转换


第9题:列表过滤

题目: 从列表中筛选出所有偶数,返回新列表并输出。

Python
def filter_even(lst):
    result = []
    #**********begin1**********
    for num in lst                             # ❌ 错误1
    #**********end1**********
        #**********begin2**********
        if num % 2 == 1:
            result.append(num)
        #**********end2**********
    #**********begin3**********
    return result.sort()
    #**********end3**********

nums = [1, 2, 3, 4, 5, 6, 7, 8]
even_nums = filter_even(nums)
print(f"偶数有{len(even_nums)}个:{even_nums}")

✅ 错误修正

错误位置 原代码 修正后 错误原因
begin1 for num in lst for num in lst: for 语句末尾缺少冒号
begin2 num % 2 == 1 num % 2 == 0 筛选偶数应判断余数为0,== 1 筛选的是奇数
begin3 return result.sort() return result sort() 原地排序并返回 None,不是排序后的列表

完整正确代码

Python
def filter_even(lst):
    result = []
    for num in lst:                        # ✅ 修正1:添加冒号
        if num % 2 == 0:                   # ✅ 修正2:余数为0是偶数
            result.append(num)
    return result                           # ✅ 修正3:直接返回列表

nums = [1, 2, 3, 4, 5, 6, 7, 8]
even_nums = filter_even(nums)
print(f"偶数有{len(even_nums)}个:{even_nums}")

# 输出: 偶数有4个:[2, 4, 6, 8]

解析:

  • 错误1for 语句末尾必须加冒号 :,这是 Python 的语法要求,与 whileif 等语句一致

    Python
    for num in lst       # ❌ 缺少冒号
    for num in lst:      # ✅ 语法正确
    
  • 错误2:偶数的定义是能被 2 整除的数,即 num % 2 == 0num % 2 == 1 判断的是奇数,会把奇数添加到结果列表中,与题目要求相反

    Python
    1
    2
    3
    4
    5
    6
    # 偶数判断
    4 % 2  # 0 → 偶数 ✅
    3 % 2  # 1 → 奇数
    
    # 判断偶数:num % 2 == 0
    # 判断奇数:num % 2 == 1
    
  • 错误3list.sort() 是原地排序方法,它会修改列表本身并返回 None,不会返回排序后的新列表。return result.sort() 等同于 return None

    Python
    1
    2
    3
    4
    5
    6
    7
    lst = [3, 1, 2]
    lst.sort()      # 原地排序,lst 变为 [1, 2, 3],返回 None
    print(lst)      # [1, 2, 3]
    
    lst = [3, 1, 2]
    result = lst.sort()  # result = None ❌
    result = sorted(lst) # result = [1, 2, 3] ✅
    

    本题中偶数列表 [2, 4, 6, 8] 已经是有序的,不需要排序,直接 return result 即可

🔑 知识点:列表排序与奇偶判断

  • sort()sorted() 的区别:
方法 是否原地修改 返回值 用法
lst.sort() 是,修改原列表 None lst.sort() → 列表变为排序后的
sorted(lst) 否,返回新列表 排序后的新列表 new = sorted(lst) → 原列表不变
  • 奇偶判断:

    • 偶数:num % 2 == 0(能被 2 整除)
    • 奇数:num % 2 == 1(除以 2 余 1)
  • 常见 sort() 返回 None 的陷阱:

    Python
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # ❌ 错误:sort() 返回 None
    result = my_list.sort()
    
    # ✅ 正确写法1:先排序再返回
    my_list.sort()
    return my_list
    
    # ✅ 正确写法2:使用 sorted()
    return sorted(my_list)
    

📖 拓展
Python
# 方法2:列表推导式(推荐,简洁高效)
def filter_even_v2(lst):
    return [num for num in lst if num % 2 == 0]

# 方法3:filter 函数
def filter_even_v3(lst):
    return list(filter(lambda x: x % 2 == 0, lst))

# 方法4:同时筛选奇偶
nums = [1, 2, 3, 4, 5, 6, 7, 8]
evens = [n for n in nums if n % 2 == 0]
odds = [n for n in nums if n % 2 == 1]
print(f"偶数:{evens}")  # [2, 4, 6, 8]
print(f"奇数:{odds}")   # [1, 3, 5, 7]

# 方法5:按条件分组
from collections import defaultdict
groups = defaultdict(list)
for n in nums:
    groups["偶数" if n % 2 == 0 else "奇数"].append(n)
print(dict(groups))  # {'奇数': [1, 3, 5, 7], '偶数': [2, 4, 6, 8]}

📌 记忆要点

  • forwhileif 等语句末尾必须加冒号 :

  • 偶数判断:num % 2 == 0,奇数判断:num % 2 == 1

  • sort() 原地排序返回 Nonesorted() 返回新列表

  • 不要写 return lst.sort(),应该 return lstreturn sorted(lst)


第10题:阶乘计算

题目: 计算并输出输入正整数的阶乘。

Python
def factorial(n):
    #**********begin1**********
    result = 0                                 # ❌ 错误1
    #**********end1**********
    #**********begin2**********
    for i in range(1, n):                      # ❌ 错误2
    #**********end2**********
        result *= i
    return result

n = int(input("请输入一个正整数:"))
#**********begin3**********
print(str(n) + "的阶乘为:" + factorial(n))    # ❌ 错误3
#**********end3**********

✅ 错误修正

错误位置 原代码 修正后 错误原因
begin1 result = 0 result = 1 累乘初始值应为1,0乘以任何数都为0
begin2 range(1, n) range(1, n + 1) range(1, n) 不包含 n,少乘了 n
begin3 + factorial(n) + str(factorial(n)) 或 f-string factorial() 返回整数,不能与字符串直接拼接

完整正确代码

Python
def factorial(n):
    result = 1                             # ✅ 修正1:初始值为1
    for i in range(1, n + 1):              # ✅ 修正2:range(1, n+1) 包含n
        result *= i
    return result

n = int(input("请输入一个正整数:"))
print(f"{n}的阶乘为:{factorial(n)}")      # ✅ 修正3:f-string

# 输入 5 → 输出: 5的阶乘为:120
# 输入 6 → 输出: 6的阶乘为:720
# 输入 10 → 输出: 10的阶乘为:3628800

解析:

  • 错误1:阶乘是连乘运算,初始值必须为 1。result = 0 会导致 result *= i 始终为 0,因为 0 乘以任何数都等于 0

    Python
    1
    2
    3
    4
    5
    6
    # 阶乘计算过程(n=5):
    # 正确:result = 1
    # 1 * 1 = 1 → 1 * 2 = 2 → 2 * 3 = 6 → 6 * 4 = 24 → 24 * 5 = 120 ✅
    
    # 错误:result = 0
    # 0 * 1 = 0 → 0 * 2 = 0 → 0 * 3 = 0 → ... → 永远是0 ❌
    

    累加运算初始值为 0,累乘运算初始值为 1,这是基本原则

  • 错误2range(1, n) 生成 1 到 n-1 的整数,不包含 n。阶乘 n! = 1 * 2 * 3 * ... * n,必须包含 n。应改为 range(1, n + 1)

    Python
    1
    2
    3
    # n=5 时:
    # range(1, 5) → 1, 2, 3, 4 → 结果 = 24(少乘了5)❌
    # range(1, 6) → 1, 2, 3, 4, 5 → 结果 = 120 ✅
    
  • 错误3factorial(n) 返回整数,"的阶乘为:" + 120 会报 TypeError。需要转为字符串或使用 f-string

🔑 知识点:累乘与 range

  • 累加 vs 累乘的初始值:
运算 初始值 示例
累加 += 0 total = 0; total += x
累乘 *= 1 product = 1; product *= x
  • range(start, stop) 的范围是 [start, stop)不包含 stop
代码 生成的数 说明
range(1, 5) 1, 2, 3, 4 不包含 5
range(1, 6) 1, 2, 3, 4, 5 包含 5
  • 要包含 n,必须写 range(1, n + 1)

  • 字符串与数值拼接:

    • f-string:f"{n}的阶乘为:{factorial(n)}"(推荐)
    • str() 转换:str(n) + "的阶乘为:" + str(factorial(n))
📖 拓展
Python
# 方法2:递归实现阶乘
def factorial_recursive(n):
    if n <= 1:
        return 1
    return n * factorial_recursive(n - 1)

# 方法3:使用 math.factorial(Python 内置)
import math
print(math.factorial(5))  # 120

# 方法4:reduce 函数
from functools import reduce
def factorial_reduce(n):
    return reduce(lambda x, y: x * y, range(1, n + 1), 1)

# 阶乘增长速度
# 1! = 1
# 5! = 120
# 10! = 3628800
# 20! = 2432902008176640000
# Python 支持任意大整数,不会溢出

# 阶乘的常见应用:排列组合
# 排列数 A(n,m) = n! / (n-m)!
# 组合数 C(n,m) = n! / (m! * (n-m)!)
def combination(n, m):
    return math.factorial(n) // (math.factorial(m) * math.factorial(n - m))

print(f"C(5,2) = {combination(5, 2)}")  # C(5,2) = 10

📌 记忆要点

  • 累乘初始值为 1,累加初始值为 0

  • range(1, n) 不包含 n,要包含 n 需写 range(1, n + 1)

  • 整数与字符串拼接用 f-string 或 str() 转换