学径 LearnPath

CAICP-E · Python 编程基础

找东西和修 bug

从左到右找名字,读懂报错,补上一行。

讲解模式

这一节要学会什么

#what

这节课学两种本领。一是简单 算法。 二是 调试

算法这里要求仿用。题目会给提示或注释。 不要求把每一行都默写下来。

你会在架子上按顺序找一个名字。这就是 查找enumerate 若出现,照着抄就行,不必自己发明。

调试要会三件事: 读报错最后一行。补上缺的冒号、缩进或引号。 分清语法错误和名字错误。

找书和改错别字

#hook

书架上找一本数学书。一种办法:从左到右一本本看。 书如果按名字排好了,可以折半找。猜数字也一样:每次问中间那个。

程序写错了,也会留线索。红字报错像老师批改。 先看最后一行说了什么。再改一处。

查找和修 bug

如果觉得有点难 查找先从左边第一格问起。 调试先看报错最后一行说了什么。

如果已经会了 给顺序查找加上「找不到」的提示。 再故意写错一行,读报错改回来。 二分查找只仿用,不要自己发明 left、right、mid。

顺序查找:从左到右问

#explore-linear

顺序查找:从左到右一本本问。架子乱放时,这个办法最老实。

先记下格子号。从 0 开始,看完一格加 1。

python
# 顺序查找:一个一个比
names = ["小明", "小红", "小派"]
target = "小红"
i = 0
found = False
while i < len(names):
    if names[i] == target:
        print("在第", i, "格")
        found = True
        break
    i = i + 1
if not found:
    print("没找到")

找到就印格子号。用 break 可以提前停。 找不到就保持 False,再告诉你没找到。

也可以写成:

python
for i in range(len(names)):
    if names[i] == target:
        print("在第", i, "格")
        break

意思一样。都是从左边第一格走到右边。

从左到右翻一本乱书架

列表不必先排序。这是最朴素的查找。

注释已经告诉你思路。仿用时,先读注释。 再把循环和 if 填完整。

enumerate:照着抄,不必发明

#explore-enum

走过列表时,有时既要格子号,又要格子里的东西。主路仍是 i = 0i = i + 1, 或者 for i in range(len(names))

照着抄,不必发明 题目会把这一行写好。 你只要会填后面的 ifprint

python
shelf = ["语文", "数学", "英语"]
for i, book in enumerate(shelf):
    print(i, book)

会印出 0 语文1 数学2 英语i 是编号,book 是这一格里的书。 这一段看见了会用就行。

折半猜数:想法先记住

#explore-binary

老师心里想一个 1 到 16 的数。你每次猜正中间。

先猜 8。太大了,去左半边 1 到 7。 太小了,去右半边 9 到 16。范围越缩越小。

这就是二分查找的想法。前提:数字已经从小到大排好。 没排好时,不要折半,用顺序查找。

下面这段只用来仿用。不要自己发明 leftrightmid。 题目若出现,会把这一段写好。

python
# 仿用:先确认列表已排序。不要自己发明。
nums = [1, 3, 5, 7, 9]
target = 7
left = 0
right = len(nums) - 1
found = False
while left <= right:
    mid = (left + right) // 2  # 中间位置
    if nums[mid] == target:
        found = True
        break
    elif nums[mid] < target:
        left = mid + 1  # 去右半边
    else:
        right = mid - 1  # 去左半边
print(found)

你只要能读注释,知道: 中间是 mid。比较后缩小范围。

排好的书从中间翻,往左或往右

猜数字时,别人会给你提示:太大了、太小了。程序里的 if,就是在听这个提示。

报错先看最后一行

#explore-error

程序出错会说话。先看最后一行的错误名字。 再看它指出的行号。

红框标出最后一行 NameError

先认准两种。

SyntaxError:语法错。句子还没写完。 常忘冒号、引号不成对、括号不成对。

python
print("你好)

少了一个盖子。电脑看不懂这句话。

python
if score >= 60
    print("及格")

if 后面少了冒号。这也是语法错误。

NameError:名字还没定义。单词电脑不认识。

python
print(score)

score 还没有赋值。电脑会说:这个名字我没见过。

缩进不对,常常是 IndentationError。它也和语法有关。 if 下面那一行必须缩进。

python
if score >= 60:
print("及格")

第二行没有缩进,会报错。

读报错时,不要只看第一行英文。最后一行通常直接告诉你:错的类型叫什么。

一次只补一处

#explore-fix

看这段残缺代码:

python
# 目标:打印 1 到 3
for n in range(1, 4)
    print(n)

缺了冒号。这是语法错误。 补上 : 就能跑。

只补上 for 后面缺的冒号

再看哪一行错了:

python
print("你好)

引号没盖严。先改这一处。 再跑。不要同时改十处。

顺序查找缺一行「找到就停」。最合适的常常是 break。 不是 continue,也不是 pass

python
# 顺序查找 target 是否在 names 里
found = False
for n in names:
    if n == target:
        found = True
        _____

横线处填 break

修 bug 的步骤可以记:

  1. 读最后一行报错
  2. 看它指出的行号
  3. 对照注释想「本来要做什么」
  4. 改一处,再试一次

语法错误:句子结构坏了。名字错误:某个词还没出现过。 先分清,再动手。

这节课我学会了

#review

记住这些:

  1. 顺序查找:从左到右,i = 0i = i + 1,找到可以用 break
  2. enumerate 照着抄就行,题目会把这一行写好。
  3. 二分查找:先排好序,每次看中间。只仿用,不要自己发明。
  4. 报错最后一行最重要。缺冒号、缺引号、名字没定义,都很常见。
  5. 一次只改一处。

算法负责想步骤。调试负责把步骤写对。

Python 主线先到这儿。会找,也会修,就可以自己写更多小工具了。

试一试

#evaluate

看完就来检查一下。选错了也可以再想。

单选题

哪一行有语法错误

下面程序想打印 1 到 3。哪一行写错了?\n1 for n in range(1, 4)\n2 print(n)\n3 print(「结束」)

单选题

补全残缺代码

注释写着:顺序查找 target 是否在 names 里。残缺如下:\nfound = False\nfor n in names:\n if n == target:\n found = True\n _____\n应填哪一句最合适?

单选题

顺序查找找到谁

names = [「小明」, 「小红」, 「小派」]。i 从 0 开始,每次 i = i + 1,找「小红」。找到时 i 是?

多选题

查找和调试

下列说法正确的有哪些?可以多选。

可多选

未登录时不会保存学习进度