Chọn đến phần học sinh cần nhanh chóng thông qua mục lục bằng cách click đến phần đó
Câu hỏi mở đầu
Đề bài: Một chương trình hoàn chỉnh được mô tả như Hình 29.1: Tiếp nhận các dữ liệu đầu vào, xử lí theo yêu cầu bài toán và đưa ra kết quả đúng theo yêu cầu. Theo em nếu chương trình có lỗi, thì các lỗi này sẽ như thế nào và có thể ở đâu?
Lời giải:
Theo sơ đồ Hình 29.1 (Input → Chương trình → Output), lỗi có thể xảy ra ở $3$ vị trí:
- Tại Input: Khi người dùng nhập dữ liệu sai khuôn dạng (ví dụ: yêu cầu nhập số nguyên nhưng nhập chữ hoặc số thực).
- Trong Chương trình: Có thể có lỗi cú pháp (viết sai quy tắc Python), lỗi khi đang thực hiện (chia cho $0$, chỉ số vượt giới hạn,…), hoặc lỗi logic (thuật toán sai).
- Tại Output: Kết quả ra không đúng so với yêu cầu — đây thường là hệ quả của lỗi logic.
1. Nhận biết lỗi chương trình
Hoạt động 1 trang 141 – 142
Đề bài: Quan sát các trường hợp chương trình gặp lỗi như sau, từ đó nhận biết và phân biệt một số loại lỗi của chương trình.
Lời giải:
Qua $4$ trường hợp trong SGK, ta phân biệt được 3 loại lỗi chính trong Python:
Trường hợp 1 – Lỗi cú pháp (Syntax Error):
>>> while True print("Hello")
SyntaxError: invalid syntax
→ Viết sai quy tắc Python (thiếu dấu :). Chương trình dừng ngay lập tức trước khi chạy.
Trường hợp 2 – Lỗi ngoại lệ (ValueError):
>>> n = int(input("Nhập số nguyên n: "))
Nhập số nguyên n: 1.5
ValueError: invalid literal for int() with base 10: '1.5'
→ Hàm int() không chuyển được xâu "1.5" thành số nguyên. Lỗi này xảy ra khi đang thực hiện (Runtime).
Trường hợp 3 – Lỗi ngoại lệ (IndexError):
A = [1,3,10,0]
for i in range(5):
print(A[i], end = " ")
→ Danh sách $A$ chỉ có $4$ phần tử (chỉ số $0$ đến $3$), nhưng range(5) cho $i$ chạy đến $4$ → truy cập A[4] vượt giới hạn. Lỗi IndexError: list index out of range.
Trường hợp 4 – Lỗi logic:
# Tính tổng của ba số nguyên dương đầu tiên
>>> s = 0
>>> for i in range(3):
s = s + i
>>> print(s)
3
→ Chương trình chạy bình thường, không báo lỗi nhưng kết quả ra $3$ trong khi đáp án đúng là $1 + 2 + 3 = 6$. Lí do: range(3) cho $i = 0, 1, 2$ chứ không phải $1, 2, 3$.
Tổng kết – $3$ loại lỗi của chương trình Python:
| Loại lỗi | Mã lỗi | Đặc điểm |
|---|---|---|
| Lỗi cú pháp | SyntaxError |
Viết sai cú pháp, chương trình dừng ngay trước khi chạy. |
| Lỗi ngoại lệ (Exceptions Error) | ValueError, IndexError,… |
Lỗi xảy ra khi đang thực hiện, chương trình dừng và báo mã lỗi. |
| Lỗi logic | (không có mã lỗi) | Chương trình chạy bình thường nhưng cho kết quả sai. |
Câu hỏi củng cố mục 1 trang 142
Đề bài:
1. Khi gõ sai cú pháp một lệnh, chương trình sẽ dừng lại và báo lỗi, đó là lỗi loại gì?
Lời giải:
→ Đó là lỗi cú pháp (SyntaxError).
2. Bài toán yêu cầu sắp xếp dãy số ban đầu thành dãy tăng dần. Giả sử dãy số ban đầu là $[3, 1, 8, 10, 0]$. Kết quả thu được dãy $[1, 3, 8, 10, 0]$. Chương trình có lỗi không? Nếu có thì lỗi đó thuộc loại gì?
Lời giải:
→ Có lỗi.
Giải thích: Dãy đúng phải là $[0, 1, 3, 8, 10]$ (tăng dần), nhưng kết quả lại là $[1, 3, 8, 10, 0]$ (số $0$ vẫn ở cuối). Chương trình chạy bình thường, không báo lỗi nhưng kết quả sai.
→ Đây là lỗi logic trong chương trình.
2. Một số lỗi ngoại lệ thường gặp
Hoạt động 2 trang 143
Đề bài: Đọc, thảo luận để nhận biết một số lỗi ngoại lệ thường gặp trong chương trình Python.
Lời giải:
Bảng tổng hợp $7$ mã lỗi ngoại lệ thường gặp:
| Mã lỗi | Mô tả lỗi |
|---|---|
ZeroDivisionError |
Lệnh thực hiện phép chia cho $0$. |
IndexError |
Truy cập phần tử danh sách nhưng chỉ số vượt quá giới hạn. |
NameError |
Tên (biến/hàm) không tồn tại (chưa được định nghĩa). |
TypeError |
Sai kiểu dữ liệu (vd: dùng chỉ số không là số nguyên, dùng phép toán với kiểu sai). |
ValueError |
Sai giá trị của đối số (vd: int("1.55")). |
IndentationError |
Lệnh thụt vào không thẳng hàng hoặc không đúng vị trí. |
SyntaxError |
Lỗi cú pháp. |
Câu hỏi củng cố mục 2 trang 143
Đề bài: Hãy nêu mã lỗi ngoại lệ của mỗi lệnh sau nếu xảy ra lỗi.
a) A[1.5] b) int("abc") c) "10"*3.5 d) 12 + x(10)
Lời giải:
| Lệnh | Mã lỗi | Lý do |
|---|---|---|
a) A[1.5] |
TypeError |
Chỉ số truy cập danh sách phải là số nguyên, không phải $1.5$. |
b) int("abc") |
ValueError |
Xâu "abc" không phải dạng số nên không chuyển được sang số nguyên. |
c) "10"*3.5 |
TypeError |
Phép nhân xâu chỉ chấp nhận số nguyên, không nhận $3.5$. |
d) 12 + x(10) |
NameError |
Tên x chưa được định nghĩa (giả sử x chưa khai báo là hàm). |
Thực hành trang 143 – 144
Nhiệm vụ 1 trang 143 – 144
Đề bài: Viết chương trình nhập các số nguyên $m$, $n$ từ bàn phím, cách nhau bởi dấu cách. Chương trình đưa ra tổng, hiệu, thương của hai số đã nhập.
Hướng dẫn thực hành:
Ý tưởng: Dùng input() nhập một xâu, dùng split() tách thành danh sách, dùng int() chuyển sang số nguyên rồi tính.
s = input("Nhập hai số m, n cách nhau bởi dấu cách: ")
sline = s.split()
m, n = int(sline[0]), int(sline[1])
print("Tổng, hiệu, thương 2 số đã nhập là:", m+n, m-n, m/n)
Các khả năng sinh lỗi:
| Tình huống | Mã lỗi |
|---|---|
Các số $m$, $n$ nhập vào không phải số nguyên (vd: nhập 1.5 hay abc). |
ValueError |
| Giữa hai số $m$, $n$ không có dấu cách (chỉ nhập được $1$ phần tử). | IndexError (khi truy cập sline[1]) |
| Số $n$ nhập vào là $0$ → phép chia $m/n$ bị chia cho $0$. | ZeroDivisionError |
Nhiệm vụ 2 trang 144
Đề bài: Viết chương trình nhập số tự nhiên $n$ và nhập lần lượt $n$ số nguyên đưa vào danh sách số $A$. Sau khi nhập xong in danh sách $A$ ra màn hình.
Hướng dẫn thực hành:
Ý tưởng: Nhập $n$, sau đó dùng vòng lặp for $n$ lần để nhập từng số và append() vào danh sách $A$.
n = int(input("Nhập số tự nhiên n: "))
A = []
for k in range(n):
num = int(input("Nhập số thứ " + str(k+1) + " : "))
A.append(num)
print("Dãy đã nhập:", A)
Các khả năng sinh lỗi:
| Tình huống | Mã lỗi |
|---|---|
Số $n$ nhập vào không phải số nguyên (vd: 2.5, abc). |
ValueError |
| Mỗi số hạng nhập vào không phải số nguyên. | ValueError |
Luyện tập trang 144
Luyện tập 1 trang 144
Đề bài: Các lệnh sau có sinh lỗi chương trình không? Nếu có thì mã lỗi là gì?
a)
>>> A = [1,3,5,10,0]
>>> for k in range(1, len(A)+1):
print(A[k])
b)
>>> s1, s2 = "101010", 1010101
>>> s = s1 + s2
Lời giải:
Câu a) Có lỗi → IndexError.
Phân tích:
- $\text{len}(A) = 5$, nên
range(1, len(A)+1)=range(1, 6)→ $k$ chạy qua các giá trị $1, 2, 3, 4, 5$. - Khi $k = 5$: truy cập
A[5]nhưng $A$ chỉ có $5$ phần tử (chỉ số $0$ đến $4$) → vượt giới hạn.
→ Báo lỗi IndexError: list index out of range.
Câu b) Có lỗi → TypeError.
Phân tích:
- $s_1 = $
"101010"là xâu kí tự, $s_2 = 1010101$ là số nguyên. - Phép
s1 + s2cố cộng xâu với số → không cùng kiểu dữ liệu.
→ Báo lỗi TypeError.
Cách sửa câu b: Phải đưa hai giá trị về cùng kiểu, ví dụ:
s = s1 + str(s2)(chuyển $s_2$ thành xâu).
Luyện tập 2 trang 144
Đề bài: Để tính giá trị trung bình của một danh sách số $A$, người lập trình đã dùng lệnh sau để tính:
gttb = sum(A)/len(A)
Lệnh này có thể sinh lỗi ngoại lệ không? Nếu có thì là những lỗi gì?
Lời giải:
→ Có thể sinh $2$ loại lỗi ngoại lệ:
Lỗi 1 – ZeroDivisionError:
- Khi danh sách $A$ rỗng → $\text{len}(A) = 0$ → phép chia
sum(A) / 0→ lỗi chia cho $0$.
Lỗi 2 – TypeError:
- Khi danh sách $A$ chứa các phần tử không phải số (ví dụ: xâu kí tự) → lệnh
sum(A)không cộng được các kiểu dữ liệu khác nhau → lỗi kiểu dữ liệu.
Cách phòng tránh: Trước khi tính, nên kiểm tra
len(A) > 0và đảm bảo các phần tử trong $A$ đều là số.
Vận dụng trang 144
Vận dụng 1 trang 144
Đề bài: Giả sử em được yêu cầu viết một chương trình nhập số tự nhiên $n$ từ bàn phím, kết quả đưa ra là danh sách các ước số thực sự của $n$, tính cả $1$ và không tính $n$. Hãy viết chương trình và kiểm tra các khả năng sinh lỗi khi thực hiện chương trình.
Lời giải:
Ý tưởng: Duyệt $k$ từ $1$ đến $n – 1$, nếu $n$ chia hết cho $k$ thì $k$ là ước thực sự của $n$.
n = int(input("Nhập số tự nhiên n: "))
uoc = []
for k in range(1, n):
if n % k == 0:
uoc.append(k)
print("Các ước thực sự của", n, "là:", uoc)
Ví dụ khi chạy (nhập $n = 12$):
Nhập số tự nhiên n: 12
Các ước thực sự của 12 là: [1, 2, 3, 4, 6]
Các khả năng sinh lỗi:
| Tình huống | Mã lỗi / Hiện tượng |
|---|---|
Nhập $n$ không phải số nguyên (vd: 1.5, abc). |
ValueError |
| Nhập $n = 0$ hoặc $n = 1$. | Không lỗi nhưng uoc rỗng []. |
| Nhập $n$ âm. | Không lỗi nhưng range(1, n) rỗng → uoc rỗng. |
Vận dụng 2 trang 144
Đề bài: Em hãy viết một chương trình nhỏ để khi chạy sẽ sinh mã lỗi NameError.
Lời giải:
Ý tưởng: Lỗi NameError xảy ra khi sử dụng một tên (biến hoặc hàm) chưa được định nghĩa. Có nhiều cách để sinh ra lỗi này.
Cách 1 – Dùng biến chưa khai báo:
print(x)
Khi chạy: biến x chưa được gán giá trị → báo lỗi NameError: name 'x' is not defined.
Cách 2 – Gọi hàm chưa định nghĩa:
ham_chua_co()
Khi chạy: hàm ham_chua_co chưa được định nghĩa → báo lỗi NameError: name 'ham_chua_co' is not defined.
Cách 3 – Dùng biến cục bộ ngoài hàm:
def f():
a = 10
return a
f()
print(a)
Khi chạy: biến a chỉ tồn tại bên trong hàm f(), không tồn tại bên ngoài (theo Bài 28) → báo lỗi NameError: name 'a' is not defined.
Em chỉ cần chọn $1$ trong $3$ cách trên để minh hoạ lỗi
NameError.

Thầy Phạm Thành Danh
(Người kiểm duyệt, ra đề)
Chức vụ: Trưởng ban biên soạn môn Tin Học THPT
Trình độ: Cử nhân Sư phạm Tin học, Chứng chỉ hạng II, Chứng chỉ Tin học, Ngoại ngữ B1
Kinh nghiệm: 8+ năm kinh nghiệm tại Trường THPT Thuận Hóa
