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 trang 136
Câu hỏi mở đầu
Đề bài:
1. Một biến được định nghĩa trong chương trình chính (bên ngoài các hàm) thì sẽ được sử dụng như thế nào bên trong các hàm?
2. Một biến được khai báo bên trong một hàm thì có sử dụng được ở bên ngoài hàm đó hay không?
Lời giải:
Dự đoán trước khi học bài:
1. Biến khai báo bên ngoài hàm có thể được truy cập (đọc giá trị) ở bên trong hàm, nhưng nói chung không thể thay đổi giá trị từ bên trong hàm (trừ khi dùng từ khoá global).
2. Biến khai báo bên trong hàm chỉ có hiệu lực bên trong hàm đó, không sử dụng được ở bên ngoài hàm (gọi là biến cục bộ/địa phương).
→ Bài học này sẽ làm rõ hai vấn đề trên.
1. Phạm vi của biến khai báo trong hàm
Hoạt động 1 trang 136
Đề bài: Quan sát các lệnh sau để tìm hiểu phạm vi có hiệu lực của biến khi khai báo bên trong một hàm.
>>> def func(a,b):
n = 10
a = a*2
b = a+b
return a+b+n
>>> a = 1
>>> b = 2
>>> func(a,b)
16
>>> a,b
(1, 2)
>>> n
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
n
NameError: name 'n' is not defined
Lời giải:
Phân tích từng phần:
- Bên trong hàm
func: Các biếnn,a,bđang hoạt động. Cụ thể:n = 10,avàbđược thay đổi. - Sau khi gọi
func(a,b)(với $a = 1$, $b = 2$):- Bên trong hàm: $a = 1 \times 2 = 2$, $b = 2 + 2 = 4$, $n = 10$ → trả về $2 + 4 + 10 = 16$. ✓
- Bên ngoài hàm: $a$, $b$ vẫn không thay đổi, vẫn là $(1, 2)$.
- Khi gõ
nbên ngoài hàm: Báo lỗiNameErrorvì biếnnchỉ tồn tại bên trong hàmfunc, không tồn tại ở bên ngoài.
→ Kết luận: Trong Python, tất cả các biến khai báo bên trong hàm đều có tính địa phương (cục bộ), không có hiệu lực ở bên ngoài hàm.
Câu hỏi củng cố mục 1 trang 137
Đề bài:
1. Giả sử có các lệnh sau:
>>> a,b = 1,2
>>> def f(a,b):
a = a + b
b = b*a
return a + b
Giá trị của $a$, $b$ bằng bao nhiêu sau khi thực hiện lệnh sau?
a) f(1, 2) b) f(10, 20)
Lời giải:
Quan trọng: Các biến $a$, $b$ bên ngoài hàm là $(1, 2)$. Các tham số $a$, $b$ bên trong hàm là biến cục bộ, không ảnh hưởng đến $a$, $b$ bên ngoài.
Câu a) f(1, 2):
Bên trong hàm:
- $a = 1 + 2 = 3$
- $b = 2 \times 3 = 6$
- Trả về $3 + 6 = 9$.
Sau lời gọi, bên ngoài hàm: $a = 1$, $b = 2$ (không thay đổi).
Câu b) f(10, 20):
Bên trong hàm:
- $a = 10 + 20 = 30$
- $b = 20 \times 30 = 600$
- Trả về $30 + 600 = 630$.
Sau lời gọi, bên ngoài hàm: $a = 1$, $b = 2$ (vẫn không thay đổi).
→ Cả hai trường hợp, $a$, $b$ bên ngoài hàm vẫn giữ giá trị ban đầu $(1, 2)$.
2. Ta có thể khai báo một biến bên trong hàm trùng tên với biến đã khai báo trước đó bên ngoài hàm không?
Lời giải:
→ Có thể.
Giải thích: Biến bên trong hàm và biến bên ngoài hàm là độc lập với nhau, dù trùng tên cũng không ảnh hưởng đến nhau. Ví dụ trong Hoạt động 1, tham số $a, b$ bên trong hàm func trùng tên với $a, b$ bên ngoài nhưng vẫn hoạt động riêng biệt.
2. Phạm vi của biến khai báo ngoài hàm
Hoạt động 2 trang 137
Đề bài: Quan sát các lệnh sau, tìm hiểu phạm vi có hiệu lực của biến khi khai báo bên ngoài một hàm.
Lời giải:
Qua hai ví dụ trong SGK, ta rút ra:
Ví dụ 1 – Biến cùng tên bên trong hàm là biến cục bộ:
>>> def f(n):
t = n + 1
return t
>>> t = 10
>>> f(5)
6
>>> t
10
- Bên trong hàm có biến $t$ (cục bộ), nhận giá trị $n + 1 = 6$.
- Biến $t$ bên ngoài hàm vẫn giữ giá trị $10$, không bị thay đổi.
Ví dụ 2 – Truy cập biến ngoài hàm từ bên trong hàm:
>>> def f(a,b):
return a + b + N
>>> N = 10
>>> f(1,2)
13
- Bên trong hàm
f, biến $N$ (chưa khai báo trong hàm) được truy cập từ bên ngoài. - $f(1, 2) = 1 + 2 + 10 = 13$.
→ Tóm lại: Biến khai báo bên ngoài hàm có thể được đọc bên trong hàm.
Lưu ý quan trọng – Từ khoá global:
Nếu muốn thay đổi giá trị biến bên ngoài từ bên trong hàm, cần khai báo lại biến đó với từ khoá global:
>>> def f(n):
global t
t = 2*n + 1
return t
>>> t = 10
>>> f(1)
3
>>> t
3
Sau khi gọi f(1), biến $t$ bên ngoài đã thay đổi từ $10$ thành $3$.
Câu hỏi củng cố mục 2 trang 138
Đề bài: Giả sử hàm $f(x, y)$ được định nghĩa như sau:
>>> def f(x, y):
a = 2*(x + y)
print(a + n)
Kết quả nào được in ra khi thực hiện các lệnh sau?
n = 10
f(1, 2)
Lời giải:
Phân tích từng bước:
- Bên ngoài hàm: gán $n = 10$.
- Gọi
f(1, 2): bên trong hàm có $x = 1$, $y = 2$. - Tính $a = 2 \times (1 + 2) = 2 \times 3 = 6$.
- Lệnh
print(a + n): biến $n$ chưa khai báo trong hàm → truy cập biến $n$ bên ngoài ($n = 10$). - $a + n = 6 + 10 = 16$.
→ Kết quả in ra màn hình: $16$.
Thực hành trang 138 – 140
Nhiệm vụ 1 trang 138
Đề bài: Viết hàm với đầu vào là danh sách $A$ chứa các số và số thực $x$. Hàm trả lại một danh sách kết quả $B$ từ danh sách $A$ bằng cách chỉ giữ lại các phần tử lớn hơn hoặc bằng $x$.
Hướng dẫn thực hành:
Ý tưởng: Tạo danh sách $B$ rỗng bên trong hàm. Duyệt từng phần tử của $A$, nếu thoả mãn điều kiện $\geq x$ thì thêm vào $B$ bằng append().
def Select(A, x):
B = []
for k in range(len(A)):
if A[k] >= x:
B.append(A[k])
return B
Ví dụ kiểm tra:
>>> Select([1, 5, 3, 8, 2, 10], 4)
[5, 8, 10]
Chú ý: Biến $B$ là biến cục bộ của hàm, không ảnh hưởng đến biến cùng tên bên ngoài hàm (nếu có).
Nhiệm vụ 2 trang 138 – 139
Đề bài: Viết hàm với đầu vào là xâu kí tự Str và số $c$, đầu ra là danh sách các từ được tách ra từ xâu Str nhưng đã được chuyển thành chữ in hoa hoặc chữ in thường, hoặc chỉ chuyển kí tự đầu các từ thành chữ in hoa tuỳ thuộc vào tham số đầu vào $c$ như sau:
- Nếu $c = 0$: chuyển thành chữ in hoa.
- Nếu $c = 1$: chuyển thành chữ in thường.
- Nếu $c = 2$: chuyển kí tự đầu của mỗi từ thành chữ in hoa.
Hướng dẫn thực hành:
Ý tưởng: Dùng split() để tách xâu thành danh sách, rồi dùng các phương thức .upper(), .lower(), .title() để biến đổi từng phần tử.
def Tach_tu(Str, c):
A = Str.split()
for k in range(len(A)):
if c == 0:
A[k] = A[k].upper()
if c == 1:
A[k] = A[k].lower()
if c == 2:
A[k] = A[k].title()
return A
Ví dụ kiểm tra:
>>> Tach_tu("tin hoc lop 10", 0)
['TIN', 'HOC', 'LOP', '10']
>>> Tach_tu("Tin Hoc Lop 10", 1)
['tin', 'hoc', 'lop', '10']
>>> Tach_tu("tin hoc lop 10", 2)
['Tin', 'Hoc', 'Lop', '10']
Chú ý:
.upper()chuyển tất cả thành chữ in hoa..lower()chuyển tất cả thành chữ in thường..title()chuyển kí tự đầu mỗi từ thành chữ in hoa.
Nhiệm vụ 3 trang 139 – 140
Đề bài: Viết chương trình yêu cầu thực hiện lần lượt các việc sau, mỗi việc cần được thực hiện bởi một hàm:
- Nhập từ bàn phím một dãy các số nguyên, mỗi số cách nhau bởi dấu cách. Chuyển các số này vào danh sách $A$ và in danh sách $A$ ra màn hình.
- Trích từ danh sách $A$ ra một danh sách $B$ gồm các phần tử lớn hơn $0$. In danh sách $B$ ra màn hình.
- Trích từ danh sách $A$ ra một danh sách $C$ gồm các phần tử nhỏ hơn $0$. In danh sách $C$ ra màn hình.
Hướng dẫn thực hành:
Mỗi việc trên được viết thành một hàm:
def Nhap_Dulieu():
s = input("Nhập các số nguyên cách nhau bởi dấu cách: ")
A = s.split()
for k in range(len(A)):
A[k] = int(A[k])
return A
def getB(A):
B = []
for x in A:
if x > 0:
B.append(x)
return B
def getC(A):
C = []
for x in A:
if x < 0:
C.append(x)
return C
# Chương trình chính
A = Nhap_Dulieu()
print("Danh sách A:", A)
B = getB(A)
C = getC(A)
print("Danh sách B:", B)
print("Danh sách C:", C)
Ví dụ khi chạy (nhập 1 -2 3 -4 5 -6):
Nhập các số nguyên cách nhau bởi dấu cách: 1 -2 3 -4 5 -6
Danh sách A: [1, -2, 3, -4, 5, -6]
Danh sách B: [1, 3, 5]
Danh sách C: [-2, -4, -6]
Luyện tập trang 140
Luyện tập 1 trang 140
Đề bài: Viết hàm với đầu vào, đầu ra như sau:
- Đầu vào là danh sách
sList, các phần tử là xâu kí tự. - Đầu ra là danh sách
cList, các phần tử là kí tự đầu tiên của các xâu kí tự tương ứng trong danh sáchsList.
Lời giải:
Ý tưởng: Duyệt từng xâu trong sList, lấy kí tự đầu tiên s[0] rồi thêm vào cList.
def Lay_KyTuDau(sList):
cList = []
for s in sList:
cList.append(s[0])
return cList
Ví dụ kiểm tra:
>>> sList = ["An", "Bình", "Chiến", "Dũng"]
>>> Lay_KyTuDau(sList)
['A', 'B', 'C', 'D']
Luyện tập 2 trang 140
Đề bài: Viết hàm Tach_day() với đầu vào là danh sách $A$, đầu ra là hai danh sách $B$, $C$ được mô tả như sau:
- Danh sách $B$ thu được từ $A$ bằng cách lấy ra các phần tử có chỉ số chẵn.
- Danh sách $C$ thu được từ $A$ bằng cách lấy ra các phần tử có chỉ số lẻ.
Lời giải:
Ý tưởng: Duyệt $k$ theo chỉ số của $A$. Nếu $k$ chẵn (k % 2 == 0) → thêm vào $B$, ngược lại → thêm vào $C$.
def Tach_day(A):
B = []
C = []
for k in range(len(A)):
if k % 2 == 0:
B.append(A[k])
else:
C.append(A[k])
return B, C
Ví dụ kiểm tra:
>>> A = [10, 20, 30, 40, 50, 60]
>>> Tach_day(A)
([10, 30, 50], [20, 40, 60])
Giải thích: Các phần tử ở chỉ số chẵn $0, 2, 4$ là $10, 30, 50$ → vào $B$. Các phần tử ở chỉ số lẻ $1, 3, 5$ là $20, 40, 60$ → vào $C$.
Chú ý: Hàm có thể trả về nhiều giá trị cùng lúc bằng cách viết
return B, C.
Vận dụng trang 140
Vận dụng 1 trang 140
Đề bài: Viết hàm có hai tham số đầu vào là $m$, $n$. Đầu ra trả lại hai giá trị là:
- ƯCLN của $m$, $n$.
- Bội chung nhỏ nhất (BCNN) của $m$, $n$.
Gợi ý: Sử dụng công thức $\text{ƯCLN}(m, n) \times \text{BCNN}(m, n) = m \times n$.
Lời giải:
Ý tưởng:
- Tìm ƯCLN bằng thuật toán Euclid (đã học ở Bài 27).
- Tính BCNN $= \dfrac{m \times n}{\text{ƯCLN}}$.
def UCLN_BCNN(m, n):
a = m
b = n
while b != 0:
r = a % b
a = b
b = r
ucln = a
bcnn = (m * n) // ucln
return ucln, bcnn
Ví dụ kiểm tra:
>>> UCLN_BCNN(12, 18)
(6, 36)
Kiểm tra:
- $\text{ƯCLN}(12, 18) = 6$. ✓
- $\text{BCNN}(12, 18) = \dfrac{12 \times 18}{6} = 36$. ✓
Chú ý: Em sao chép $m$, $n$ sang $a$, $b$ trước khi tính, để không làm thay đổi giá trị ban đầu của $m$, $n$ khi tính BCNN.
Vận dụng 2 trang 140
Đề bài: Viết chương trình nhập ba số tự nhiên từ bàn phím day, month, year, các số cách nhau bởi dấu cách. Các số này biểu diễn giá trị của ngày, tháng, năm nào đó. Chương trình cần kiểm tra và in ra thông báo số liệu đã nhập vào đó có hợp lệ hay không.
Lời giải:
Ý tưởng: Viết hàm hop_le(day, month, year) trả về True nếu hợp lệ, ngược lại trả về False.
Điều kiện hợp lệ:
- $\text{year} > 0$.
- $1 \leq \text{month} \leq 12$.
- $1 \leq \text{day} \leq $ số ngày tối đa của tháng đó:
- Tháng $1, 3, 5, 7, 8, 10, 12$: $31$ ngày.
- Tháng $4, 6, 9, 11$: $30$ ngày.
- Tháng $2$: $29$ ngày nếu năm nhuận, ngược lại $28$ ngày.
def hop_le(day, month, year):
if year <= 0:
return False
if month < 1 or month > 12:
return False
# Xác định số ngày tối đa của tháng
if month in [1, 3, 5, 7, 8, 10, 12]:
max_day = 31
else:
if month in [4, 6, 9, 11]:
max_day = 30
else: # tháng 2
if year%400 == 0 or (year%4 == 0 and year%100 != 0):
max_day = 29
else:
max_day = 28
if day < 1 or day > max_day:
return False
return True
# Chương trình chính
s = input("Nhập ngày, tháng, năm cách nhau bởi dấu cách: ")
sline = s.split()
day = int(sline[0])
month = int(sline[1])
year = int(sline[2])
if hop_le(day, month, year):
print("Ngày", day, "/", month, "/", year, "là hợp lệ.")
else:
print("Ngày", day, "/", month, "/", year, "không hợp lệ.")
Ví dụ khi chạy:
Nhập ngày, tháng, năm cách nhau bởi dấu cách: 29 2 2024
Ngày 29 / 2 / 2024 là hợp lệ.
Nhập ngày, tháng, năm cách nhau bởi dấu cách: 31 4 2024
Ngày 31 / 4 / 2024 không hợp lệ.
Chú ý: Điều kiện năm nhuận đã học ở Vận dụng 2 Bài 19: năm chia hết cho $400$ hoặc chia hết cho $4$ và không chia hết cho $100$.

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
