Bài 27: Tham số của hàm – lý thuyết, Sơ đồ tư duy

I. Lý thuyết trọng tâm

1. Tham số và đối số của hàm

a) Phân biệt tham số và đối số

Đây là hai khái niệm khác nhau nhưng thường bị nhầm lẫn:

Tham số (parameter) Đối số (argument)
Khi nào Khi khai báo hàm Khi gọi hàm
Vai trò Như biến trong định nghĩa hàm Giá trị cụ thể truyền vào hàm
Ví dụ def f(a, b, c): → a, b, c là tham số f(10, x, y) → 10, x, y là đối số

b) Cách truyền dữ liệu qua tham số

>>> def f(a, b, c):       # Khai báo hàm với 3 tham số a, b, c
        return a + b + c

>>> f(1, 2, 3)            # Gọi với 3 đối số là số cụ thể
6

>>> x, y, z = 10, 20, 5
>>> f(x, y, z)            # Gọi với 3 đối số là biến đã có giá trị
35

>>> f(a, b, c)            # LỖI: a, b, c chưa được định nghĩa bên ngoài hàm
NameError: name 'a' is not defined

Giải thích chi tiết:

  • f(1, 2, 3): Đối số là số cụ thể → a=1, b=2, c=3 → trả về 1+2+3 = 6.
  • f(x, y, z): Đối số là biến đã gán giá trị → a=10, b=20, c=5 → trả về 35.
  • f(a, b, c): Đối số là biến chưa định nghĩa → Python không biết a, b, c bằng bao nhiêu → báo lỗi NameError.

c) Quy tắc truyền đối số

Khi gọi hàm, số lượng đối số phải bằng số tham số trong khai báo. Các đối số được truyền vào theo đúng thứ tự tương ứng với tham số.

Câu hỏi kiểm tra nhanh: Một hàm khai báo có một tham số, nhưng khi gọi hàm truyền hai đối số được không?

Không được. Số đối số phải bằng số tham số. Nếu truyền thừa hoặc thiếu → Python báo lỗi TypeError.

Câu hỏi kiểm tra nhanh: Giả sử hàm f có hai tham số x, y, trả lại giá trị x + 2*y. Lời gọi f(10, a) có lỗi hay không?

Phụ thuộc vào biến a. Nếu biến a đã được gán giá trị trước đó (ví dụ a = 5) → không lỗi, kết quả = 10 + 2×5 = 20. Nếu a chưa được định nghĩa → lỗi NameError (tương tự ví dụ f(a,b,c) ở trên).

2. Cách sử dụng chương trình con

a) Khi nào nên dùng chương trình con?

Nên viết hàm riêng khi:

  • Một thao tác được lặp đi lặp lại ở nhiều vị trí trong chương trình.
  • Cần chia bài toán lớn thành nhiều bài toán nhỏ, mỗi bài giải bằng một hàm.
  • Muốn chương trình rõ ràng, dễ hiểu, dễ sửa lỗi và nâng cấp.

b) Cấu trúc chương trình có sử dụng hàm

Chương trình gồm hai phần: (1) định nghĩa hàm, (2) chương trình chính gọi hàm.

Ví dụ — In các số nguyên tố ≤ n:

# Phần 1: Định nghĩa hàm
def prime(n):
    C = 0
    k = 1
    while k < n:
        if n % k == 0:
            C = C + 1
        k = k + 1
    if C == 1:
        return True
    else:
        return False

# Phần 2: Chương trình chính
n = int(input("Nhập số tự nhiên n: "))
for k in range(1, n + 1):
    if prime(k):              # gọi hàm prime() để kiểm tra
        print(k, end=" ")

Hàm prime(k) được gọi lặp lại nhiều lần (từ k=1 đến k=n), mỗi lần truyền đối số k khác nhau.

Ví dụ — Tính tổng số dương của nhiều dãy:

def tongduong(A):
    S = 0
    for k in A:
        if k > 0:
            S = S + k
    return S

# Chương trình chính
A = [0, 2, -1, 5, 10, -3]
B = [1, -10, -11, 8, 2, 0, -5]
print(tongduong(A))    # 17 (2+5+10)
print(tongduong(B))    # 11 (1+8+2)

Hàm tongduong() viết một lần, dùng được cho nhiều danh sách khác nhau bằng cách truyền đối số khác nhau.

Lợi ích: Phân chia bài toán lớn thành bài toán nhỏ, chương trình rõ ràng hơn, dễ hiệu chỉnh và nâng cấp, phát huy làm việc nhóm.

II. Phương pháp giải các dạng bài tập

Dạng 1: Viết hàm tính toán với tham số điều kiện

Phương pháp:

  • Xác định tham số chính (dữ liệu xử lí) và tham số phụ (điều kiện/cờ hiệu).
  • Dùng if...else kiểm tra tham số phụ để quyết định cách xử lí.
  • Trả kết quả bằng return.

Bài tập mẫu (SGK – Thực hành, Nhiệm vụ 1): Thiết lập hàm f_sum(A, b): nếu b == 0 thì tính tổng tất cả phần tử của A, nếu b ≠ 0 thì chỉ tính tổng các số dương.

Lời giải:

def f_sum(A, b):
    S = 0
    for x in A:
        if b == 0:
            S = S + x
        else:
            if x > 0:
                S = S + x
    return S

Giải thích: Duyệt từng phần tử x trong A. Với mỗi x, kiểm tra b: nếu b bằng 0 → cộng mọi x vào S; nếu b khác 0 → chỉ cộng khi x > 0. Cuối cùng trả S.

Ví dụ: f_sum([1,-2,3], 0) = 1+(−2)+3 = 2. f_sum([1,-2,3], 1) = 1+3 = 4.

Dạng 2: Viết hàm xử lí xâu kí tự với tham số tùy chỉnh

Phương pháp:

  • Tham số của hàm trở thành tham số cho các phương thức xâu bên trong (như split(), find()…).
  • Hàm nhận xâu + tùy chọn → xử lí → trả kết quả.

Bài tập mẫu (SGK – Thực hành, Nhiệm vụ 2): Thiết lập hàm f_dem(msg, sep) đếm số từ của xâu msg với kí tự tách từ là sep.

Lời giải:

def f_dem(msg, sep):
    xlist = msg.split(sep)
    return len(xlist)

Giải thích: split(sep) tách xâu msg theo kí tự sep thành danh sách các từ. len() đếm số phần tử → chính là số từ.

Ví dụ:

  • f_dem("Mùa thu lịch sử", " ") → tách theo dấu cách → ['Mùa', 'thu', 'lịch', 'sử'] → trả về 4.
  • f_dem("Mùa thu lịch sử", "-") → tách theo dấu gạch → ['Mùa thu lịch sử'] (không tìm thấy dấu - → cả xâu là 1 phần tử) → trả về 1.

Dạng 3: Viết hàm gộp/xử lí hai xâu kí tự

Phương pháp:

  • Xác định độ dài hai xâu, tìm phần chung (min) và phần dư.
  • Duyệt phần chung: xen kẽ kí tự từ hai xâu.
  • Nối phần còn lại của xâu dài hơn vào cuối.

Bài tập mẫu (SGK – Thực hành, Nhiệm vụ 3): Thiết lập hàm merge_str(s1, s2) gộp hai xâu bằng cách lấy lần lượt kí tự từ s1, s2. Nếu một xâu hết trước → nối phần còn lại.

Lời giải:

def merge_str(s1, s2):
    S = ""
    l1 = len(s1)
    l2 = len(s2)
    l = min(l1, l2)
    for i in range(l):
        S = S + s1[i] + s2[i]
    if l1 < l2:
        for i in range(l, l2):
            S = S + s2[i]
    if l2 < l1:
        for i in range(l, l1):
            S = S + s1[i]
    return S

Giải thích: Gọi l = min(l1, l2). Vòng for đầu lấy xen kẽ kí tự s1[i] + s2[i] cho i từ 0 đến l−1. Sau đó nếu xâu nào dài hơn thì nối phần còn lại vào S.

Ví dụ: merge_str("1111", "0000") → l1=l2=4, l=4 → xen kẽ: "10101010". merge_str("AB", "1234") → l=2 → "A1B2" + phần dư "34""A1B234".

Dạng 4: Viết chương trình có sử dụng chương trình con

Phương pháp:

  • Bước 1: Phân tích bài toán → xác định phần nào nên viết thành hàm (thao tác lặp lại, xử lí phức tạp).
  • Bước 2: Viết hàm với tham số và giá trị trả lại phù hợp.
  • Bước 3: Viết chương trình chính: nhập dữ liệu → gọi hàm → in kết quả.

Bài tập mẫu (SGK – Câu hỏi mục 2, câu 1): Dùng hàm prime(), viết chương trình in các số nguyên tố từ m đến n (1 < m < n).

Lời giải:

def prime(n):
    C = 0
    k = 1
    while k < n:
        if n % k == 0:
            C = C + 1
        k = k + 1
    if C == 1:
        return True
    else:
        return False

# Chương trình chính
m = int(input("Nhập m: "))
n = int(input("Nhập n: "))
for k in range(m, n + 1):
    if prime(k):
        print(k, end=" ")

Giải thích: Tái sử dụng hàm prime() từ Bài 26, chỉ thay range(1, n+1) bằng range(m, n+1) để duyệt từ m đến n.

Dạng 5: Viết hàm tính toán toán học đơn giản

Phương pháp:

  • Xác định rõ đầu vào (tham số) và công thức tính (đầu ra).
  • Dùng các phép toán Python phù hợp.
  • Trả kết quả bằng return.

Bài tập mẫu (SGK – Luyện tập, bài 1): Thiết lập hàm power(a, b, c) với a, b, c là số nguyên. Hàm trả lại giá trị $(a+b)^c$.

Lời giải:

def power(a, b, c):
    return (a + b) ** c

Ví dụ: power(2, 3, 2) → $(2+3)^2$ = $5^2$ = 25. power(1, 1, 10) → $(1+1)^{10}$ = $2^{10}$ = 1024.

III. Hướng dẫn thực hành

Nhiệm vụ 1: Hàm tính tổng có điều kiện

Đề bài: Thiết lập hàm f_sum(A, b): b = 0 → tổng tất cả; b ≠ 0 → tổng số dương.

def f_sum(A, b):
    S = 0
    for x in A:
        if b == 0:
            S = S + x
        else:
            if x > 0:
                S = S + x
    return S

# Kiểm tra
print(f_sum([1, -2, 3, -4, 5], 0))    # -2+1+3-4+5 = 3
print(f_sum([1, -2, 3, -4, 5], 1))    # 1+3+5 = 9

Giải thích: Tham số b đóng vai trò cờ hiệu (flag) quyết định cách tính. Trong mỗi vòng lặp, kiểm tra b trước rồi quyết định có cộng x hay không.

Nhiệm vụ 2: Hàm đếm số từ trong xâu

Đề bài: Thiết lập hàm f_dem(msg, sep) đếm số từ với kí tự tách là sep.

def f_dem(msg, sep):
    xlist = msg.split(sep)
    return len(xlist)

# Kiểm tra
print(f_dem("Mùa thu lịch sử", " "))     # 4
print(f_dem("Mùa thu lịch sử", "-"))      # 1

Giải thích: Tham số sep được truyền trực tiếp vào split(). Nếu kí tự tách không có trong xâu, split() trả về danh sách chỉ có 1 phần tử (chính xâu gốc) → kết quả = 1.

Nhiệm vụ 3: Hàm gộp hai xâu xen kẽ

Đề bài: Thiết lập hàm merge_str(s1, s2) gộp hai xâu bằng cách xen kẽ kí tự.

def merge_str(s1, s2):
    S = ""
    l1 = len(s1)
    l2 = len(s2)
    l = min(l1, l2)
    for i in range(l):
        S = S + s1[i] + s2[i]
    if l1 < l2:
        for i in range(l, l2):
            S = S + s2[i]
    if l2 < l1:
        for i in range(l, l1):
            S = S + s1[i]
    return S

# Kiểm tra
print(merge_str("1111", "0000"))    # "10101010"
print(merge_str("AB", "1234"))      # "A1B234"

Giải thích: Tìm l = chiều dài ngắn nhất. Vòng for đầu ghép xen kẽ l cặp kí tự. Sau đó nối phần dư của xâu dài hơn.

IV. Sơ đồ tư duy

1. Tham số vs Đối số

  • 1.1. Tham số (parameter): khai báo trong def, dùng như biến
  • 1.2. Đối số (argument): giá trị truyền vào khi gọi hàm
  • 1.3. Đối số có thể là: số cụ thể, biến đã gán giá trị, biểu thức
  • 1.4. Số đối số phải bằng số tham số, truyền theo đúng thứ tự
  • 1.5. Đối số chưa có giá trị → lỗi NameError

2. Sử dụng chương trình con

  • 2.1. Khi nào: thao tác lặp lại, bài toán phức tạp cần chia nhỏ
  • 2.2. Cấu trúc: phần định nghĩa hàm + phần chương trình chính
  • 2.3. Lợi ích: rõ ràng, dễ hiểu, dễ sửa, tái sử dụng, làm việc nhóm

3. Kĩ thuật viết hàm nhiều tham số

  • 3.1. Tham số cờ hiệu (flag): quyết định cách xử lí (b=0 hay b≠0)
  • 3.2. Tham số tùy chỉnh: truyền trực tiếp vào phương thức (split(sep))
  • 3.3. Nhiều tham số cùng kiểu: xử lí song song (s1, s2 trong merge_str)

V. Sai lầm thường gặp

Sai lầm Đính chính
Truyền thừa hoặc thiếu đối số so với tham số Python báo lỗi TypeError. Số đối số phải bằng số tham số. Ví dụ: hàm f(a, b) mà gọi f(1) hoặc f(1, 2, 3) đều lỗi.
Truyền biến chưa gán giá trị làm đối số Lỗi NameError. Đối số phải là giá trị cụ thể hoặc biến đã được gán trước đó. Ví dụ: f(a, b, c) mà a, b, c chưa định nghĩa → lỗi.
Nhầm tham số là biến toàn cục dùng chung Tham số là biến cục bộ bên trong hàm. Tên tham số (a, b, c) trong def f(a,b,c) không liên quan đến biến a, b, c bên ngoài hàm. Giá trị chỉ được truyền qua đối số khi gọi.
Truyền sai thứ tự đối số Đối số được gán cho tham số theo thứ tự. Ví dụ: def f(x, y): return x - y. Gọi f(10, 3) → x=10, y=3 → kết quả 7. Nhưng f(3, 10) → x=3, y=10 → kết quả −7.
Gọi f_sum(A, b) nhưng truyền b là xâu Hàm kiểm tra b == 0, nếu b là xâu (ví dụ "0") thì "0" == 0False → chạy nhánh else (tính tổng dương), không đúng ý muốn. Luôn truyền đúng kiểu dữ liệu.
Quên phần chương trình chính — chỉ viết hàm Chỉ def hàm thì hàm chưa chạy. Phải viết phần chương trình chính bên dưới để gọi hàm. Ví dụ: sau def prime(n):... cần có n = int(input(...))prime(k).
Thầy Phạm Thành Danh

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