Top 7 sai lầm thường gặp về hàm trong Python khiến học viên mới loay hoay mãi
Top 7 sai lầm thường gặp về hàm trong Python thường bắt đầu rất đơn giản: nhiều học viên viết hàm Python chạy xong, không báo lỗi cú pháp gì, nhưng kết quả lại sai hoặc gây ra lỗi ngầm rất khó phát hiện khi chương trình lớn dần lên. Chúng tôi từng chấm bài không ít bạn mới học, code chạy êm ru trên màn hình, nhưng khi kiểm tra kỹ mới thấy hàm đang âm thầm trả về sai giá trị.
Dưới đây là top 7 sai lầm thường gặp về hàm trong Python mà chúng tôi thấy lặp đi lặp lại nhiều nhất qua các lớp học viên mới. Nhận diện sớm giúp bạn sửa đúng cách trước khi nó thành thói quen khó bỏ.
Sai lầm 1: Dùng giá trị mặc định là mutable (list, dict) cho tham số hàm
Đây là lỗi kinh điển mà gần như học viên nào cũng dính ít nhất một lần. Khai báo kiểu def f(a, lst=[]) nghe có vẻ vô hại, nhưng Python chỉ tạo ra list rỗng đó đúng một lần duy nhất, khi hàm được định nghĩa, chứ không phải mỗi lần gọi hàm.
Hậu quả là list mặc định bị giữ nguyên và tích lũy dữ liệu qua nhiều lần gọi. Gọi hàm lần một, list có 1 phần tử. Gọi lần hai, list lại có thêm phần tử từ lần trước cộng dồn vào, dù bạn không hề muốn vậy. Nói dễ hiểu, tham số mặc định mutable giống như một cái hộp dùng chung cho mọi lần gọi hàm, thay vì một hộp mới mỗi lần.
Lỗi này phù hợp cảnh báo cho người mới học hàm, chưa hiểu cách Python xử lý đối tượng mutable ở tham số mặc định. Hạn chế thật của lỗi này là nó không báo lỗi cú pháp, chỉ lộ ra khi debug kỹ hoặc gặp kết quả bất thường sau nhiều lần gọi, nên rất dễ bị bỏ qua trong giai đoạn học ban đầu. Cách sửa quen thuộc là dùng None làm giá trị mặc định, rồi khởi tạo list mới bên trong thân hàm.
Sai lầm 2: Nhầm lẫn giữa return và print trong hàm
Không ít bạn mới học quen viết script đơn giản, chỉ cần thấy kết quả hiện ra màn hình là yên tâm. Vấn đề là hàm chỉ gọi print() để hiển thị kết quả mà không hề return giá trị đó ra ngoài.
Khi bạn gán biến từ hàm kiểu này, ví dụ ket_qua = tinh_tong(a, b), biến ket_qua sẽ nhận giá trị None, dù màn hình vẫn hiện đúng con số bạn mong đợi bên trong hàm. Đây là lỗi dễ bị bỏ qua nhất trong danh sách này, vì chương trình vẫn chạy, vẫn hiển thị đúng, chỉ sai ở chỗ biến nhận về không dùng tiếp được.
Lỗi này thường gặp ở người quen tư duy “làm xong là xong”, chưa quen khái niệm hàm cần trả giá trị để dùng ở chỗ khác trong chương trình. Muốn tìm hiểu kỹ hơn cách dùng đúng, bạn có thể tham khảo thêm vai trò và cách dùng lệnh return trong Python mà chúng tôi từng phân tích chi tiết.
Sai lầm 3: Không hiểu phạm vi biến (scope) local và global trong hàm
Biến khai báo bên trong hàm chỉ tồn tại bên trong hàm đó, gọi là biến local. Biến khai báo ngoài hàm, dùng chung cho cả chương trình, gọi là biến global. Nhiều học viên cố sửa đổi biến global ngay bên trong hàm mà không khai báo từ khóa global, dẫn đến lỗi hoặc hành vi không như mong đợi — Python âm thầm tạo ra một biến local trùng tên thay vì sửa biến global như bạn nghĩ.
Lỗi này hay xuất hiện ở chương trình có nhiều hàm cùng thao tác trên một biến chung, ví dụ bộ đếm tổng hoặc danh sách kết quả toàn cục. Điều đáng nói là dù có sửa bằng từ khóa global, việc lạm dụng biến global vẫn là thói quen không tốt. Chúng tôi luôn khuyên nên ưu tiên truyền tham số vào hàm và nhận giá trị trả về, thay vì để hàm âm thầm sửa trực tiếp biến bên ngoài.
Sai lầm 4: Viết hàm làm quá nhiều việc cùng lúc, khó tái sử dụng
Một hàm vừa đọc file, vừa xử lý dữ liệu, vừa in kết quả ra màn hình, vừa ghi ngược lại file khác — nghe có vẻ tiện vì gói gọn mọi thứ vào một chỗ, nhưng lại là cơn ác mộng khi cần kiểm thử hoặc tái sử dụng ở nơi khác trong dự án.
Chúng tôi thường gặp tình huống này ở học viên chuyển từ viết script nhỏ sang làm dự án lớn hơn một chút. Muốn kiểm tra riêng phần xử lý dữ liệu có đúng không, bạn buộc phải chạy luôn cả phần đọc file và ghi file kèm theo, dù không cần thiết. Việc tách hàm nhỏ hợp lý, mỗi hàm chỉ làm đúng một việc, cần thời gian thực hành mới quen tay, không có công thức cố định áp dụng cho mọi trường hợp. Kinh nghiệm chúng tôi hay chia sẻ là: nếu mô tả một hàm mà phải dùng chữ “và” nhiều lần, đó là dấu hiệu nên tách hàm đó ra.
Sai lầm 5: Quên xử lý trường hợp tham số truyền vào không hợp lệ
Hàm giả định người dùng luôn truyền đúng kiểu dữ liệu mong muốn, chẳng hạn luôn là số, luôn là chuỗi ký tự. Thực tế dữ liệu đến từ người dùng nhập tay hoặc file bên ngoài thường không đẹp như vậy.
Lỗi này đặc biệt nguy hiểm với hàm dùng trong chương trình nhận dữ liệu đầu vào từ bên ngoài, vì một giá trị sai kiểu có thể làm cả chương trình dừng đột ngột giữa chừng. Nhưng cũng cần cân bằng: kiểm tra quá nhiều điều kiện đầu vào khiến hàm trở nên cồng kềnh, khó đọc. Chúng tôi thường khuyên học viên chỉ kiểm tra những trường hợp thực sự có khả năng xảy ra trong bài toán của mình, thay vì cố phòng thủ cho mọi tình huống tưởng tượng.
Sai lầm 6: Dùng đệ quy (recursion) mà không có điều kiện dừng rõ ràng
Đệ quy, nói đơn giản, là một hàm tự gọi lại chính nó để giải quyết một bài toán nhỏ hơn. Nhiều học viên mới học đệ quy quên mất phần quan trọng nhất: điều kiện dừng, hay còn gọi là base case, để hàm biết lúc nào ngừng gọi lại chính nó.
Thiếu điều kiện dừng, hàm sẽ gọi chính nó liên tục cho tới khi Python báo lỗi RecursionError vì vượt quá giới hạn độ sâu gọi hàm cho phép. Lỗi này thường gặp ở người mới học đệ quy, thường quên kiểm tra kỹ điều kiện dừng trước khi bắt tay viết phần logic chính. Một điều chúng tôi muốn nhấn mạnh thêm: đệ quy không phải lúc nào cũng là cách tối ưu. Với bài toán đơn giản như tính tổng một dãy số, dùng vòng lặp thường dễ hiểu và ít tốn tài nguyên hơn hẳn.
Sai lầm 7: Không đặt tên hàm và tham số rõ nghĩa, gây khó hiểu khi đọc lại code
Đặt tên hàm như f1, xu_ly, hay tham số như a, b có thể tiết kiệm vài giây gõ phím lúc viết, nhưng lại khiến chính bạn hoặc đồng nghiệp mất hàng chục phút để hiểu đoạn code đó làm gì khi đọc lại sau vài tuần.
Lỗi này ảnh hưởng tới mọi người viết code Python, không riêng học viên mới, nhưng đặc biệt nghiêm trọng khi làm việc nhóm hoặc chia sẻ code cho người khác đọc. Đặt tên rõ nghĩa như tinh_diem_trung_binh thay vì f1 cần thêm vài giây suy nghĩ, nhưng lợi ích lâu dài về khả năng bảo trì code là rất lớn.
Tóm tắt top 7 sai lầm thường gặp về hàm trong Python và cách nhận diện nhanh
Ba lỗi dưới đây là những lỗi chúng tôi thấy học viên hỏi lại nhiều nhất, tổng hợp lại để bạn tiện đối chiếu khi tự rà soát code của mình:
- Tham số mặc định mutable: dấu hiệu nhận biết là dữ liệu tích lũy qua nhiều lần gọi hàm dù không truyền gì thêm; hướng khắc phục là dùng None làm mặc định rồi khởi tạo list mới bên trong hàm.
- Nhầm return và print: dấu hiệu nhận biết là biến nhận giá trị None sau khi gọi hàm dù màn hình hiện đúng; hướng khắc phục là luôn dùng return khi cần lấy kết quả để dùng tiếp ở chỗ khác.
- Thiếu điều kiện dừng đệ quy: dấu hiệu nhận biết là lỗi RecursionError khi chạy chương trình; hướng khắc phục là kiểm tra kỹ base case trước khi viết phần logic đệ quy chính.
Cách rèn thói quen viết hàm Python chuẩn ngay từ khi mới học
Tập thói quen test hàm với nhiều bộ dữ liệu đầu vào khác nhau trước khi ghép vào chương trình lớn hơn. Đừng chỉ thử với một trường hợp “đẹp” rồi yên tâm hàm đã đúng — thử cả trường hợp rỗng, trường hợp số âm, trường hợp chuỗi thay vì số, để xem hàm phản ứng ra sao.
Một thói quen khác chúng tôi hay khuyên là đọc lại code sau vài ngày, tự hỏi liệu hàm mình viết có dễ hiểu, dễ tái sử dụng hay không. Nếu bạn muốn tra cứu nhanh cú pháp một số hàm dựng sẵn của Python trong lúc luyện tập, có thể xem thêm cách dùng hàm đếm phần tử count trong Python hoặc cách dùng hàm đo độ dài len trong Python để hiểu thêm cách các hàm chuẩn của Python được thiết kế.
Với người vừa học Python vừa cân nhắc lộ trình học lập trình bài bản hơn
Ngoài việc tự sửa các lỗi thường gặp về hàm kể trên, nhiều học viên mới còn quan tâm đến việc chọn một khóa học lập trình bài bản, có cam kết việc làm rõ ràng, để rút ngắn thời gian tự mày mò một mình. Tự học vẫn tốt, nhưng có người hướng dẫn chỉ ra đúng lỗi ngay khi mới phát sinh giúp tiết kiệm không ít thời gian dò lỗi trong im lặng.
Những điều chưa thể khẳng định chắc chắn, cần người học tự kiểm chứng thêm
Mức độ phổ biến của từng sai lầm nêu trên có thể khác nhau tùy môi trường học tập và tài liệu tham khảo của mỗi người, chúng tôi không có số liệu thống kê chính xác cho toàn bộ cộng đồng học Python tại Việt Nam. Một số thói quen viết code được xem là “chuẩn” cũng còn phụ thuộc vào quy ước riêng của từng công ty, từng dự án khi đi làm thực tế, nên bạn nên linh hoạt điều chỉnh khi bước vào môi trường làm việc cụ thể. Nếu cần công cụ hỗ trợ soạn thảo và kiểm tra cú pháp khi luyện tập, có thể tham khảo thêm free-php-editor.com như một lựa chọn bên ngoài để so sánh với công cụ đang dùng.
Câu hỏi thường gặp
Tại sao hàm Python trả về None dù chương trình không báo lỗi gì?
Vì hàm chỉ dùng print() để hiển thị kết quả mà quên return giá trị đó ra ngoài. Chương trình vẫn chạy bình thường, chỉ có biến nhận về từ hàm là rỗng.
Khi nào nên dùng đệ quy thay vì vòng lặp for, while trong Python?
Nên dùng đệ quy khi bài toán tự nhiên chia thành các bài toán con giống hệt nhau, như duyệt cây thư mục. Với bài toán tuyến tính đơn giản như cộng dồn dãy số, vòng lặp thường dễ hiểu và nhanh hơn.
Làm sao tránh lỗi tham số mặc định là list trong hàm Python?
Dùng None làm giá trị mặc định cho tham số, sau đó kiểm tra trong thân hàm: nếu tham số là None thì mới khởi tạo một list rỗng mới. Cách này đảm bảo mỗi lần gọi hàm đều có list riêng, không bị dùng chung.
Viết hàm quá dài có ảnh hưởng gì đến hiệu suất và khả năng bảo trì code không?
Về hiệu suất chạy, hàm dài hay ngắn thường không khác biệt đáng kể. Vấn đề chính nằm ở khả năng bảo trì: hàm càng dài, càng làm nhiều việc, càng khó kiểm thử và khó tái sử dụng ở nơi khác trong dự án.
