DHDataHọc
TheoryLesson 21/304 min read+10 XP

Giá trị trả về

Bạn sẽ học được

  • return kết thúc hàm và trả giá trị.
  • Hàm không có return trả None.
  • Trả nhiều giá trị bằng tuple.
  • Thoát sớm và tránh lồng nhánh.
  • Khác biệt giữa print và return — lỗi của người mới.

Khái niệm cốt lõi

return làm hai việc: kết thúc hàm ngay và giao giá trị cho nơi gọi:

code
def min_max(nums):
    return min(nums), max(nums)

low, high = min_max([4, 9, 1])
print(low, high)
code
1 9

Dấu phẩy tạo một tuple (1, 9). Phép gán mở gói tuple thành hai biến. Hàm không trả về hai giá trị theo nghĩa kỹ thuật — nó trả một tuple, và Python cho phép viết gọn.

Có thể trả nguyên tuple nếu người gọi muốn:

code
result = min_max([4, 9, 1])
print(result)
code
(1, 9)

Không return thì trả None

Mọi hàm trong Python đều trả một giá trị. Không có return, hoặc return trần, thì giá trị là None:

code
def chao(name):
    print(f"Xin chào {name}")

result = chao("An")
print(result)
code
Xin chào An
None

chao in ra nhưng không trả gì, nên result là None. Hàm print cũng vậy — nó trả None:

code
result = print("hello")
print(result)
code
hello
None

Đây là nguồn gốc của lỗi TypeError: unsupported operand type(s) for +: 'NoneType' and 'str' khi ai đó viết msg = print(...) rồi nối chuỗi.

printreturn
Tác dụngHiện ra màn hìnhGiao giá trị cho nơi gọi
Giá trị hàmNoneGiá trị sau return
Dùng lại đượcKhôngCó
Kiểm thửPhải bắt stdoutSo sánh giá trị

Hàm chỉ print là ngõ cụt: kết quả không dùng được cho tính toán tiếp. Trong xử lý dữ liệu, gần như luôn nên return; chỉ print ở lớp ngoài cùng (CLI, debug).

code
# Không nên
def tong(nums):
    print(sum(nums))

# Nên
def tong(nums):
    return sum(nums)

print(tong([1, 2, 3]) * 2)

Thoát sớm

return dừng hàm ngay tại dòng đó; mọi lệnh sau không chạy:

code
def classify(score):
    if score < 0:
        return "không hợp lệ"
    if score >= 90:
        return "A"
    return "B"

print(classify(-1), classify(95), classify(60))
code
không hợp lệ A B

Cách viết này phẳng, mỗi điều kiện loại một trường hợp rồi thoát. So với lồng if/else, nó giảm một cấp thụt lề và dễ đọc hơn khi có nhiều điều kiện.

Code sau return trong cùng nhánh là không bao giờ chạy. Đôi khi điều này vô hại, nhưng thường là dấu hiệu logic sai hoặc code chết cần xoá. Editor và lint có thể cảnh báo "unreachable code".

Trả None có chủ đích

Khi hàm không có kết quả hợp lệ, trả None là quy ước:

code
def doc_diem(raw):
    try:
        score = float(raw)
    except (TypeError, ValueError):
        return None
    if not 0 <= score <= 100:
        return None
    return score

Người gọi phải kiểm tra:

code
score = doc_diem("abc")
if score is None:
    print("Dữ liệu không hợp lệ")
else:
    print(f"Điểm: {score}")

Trả None tách biệt với trả 0 — điều mà return 0 cho trường hợp lỗi sẽ làm mất. Nếu lỗi cần thông tin chi tiết hơn (None không nói lý do), có thể trả tuple (value, error) hoặc ném exception. Với bài toán nhỏ, None là đủ.

Hàm là giá trị

Trong Python, hàm là đối tượng, nên có thể trả hàm từ hàm khác:

code
def tao_bo_dem():
    count = 0

    def dem():
        nonlocal count
        count += 1
        return count

    return dem

bo_dem = tao_bo_dem()
print(bo_dem(), bo_dem())
code
1 2

Đây là closure. Hàm dem được trả ra ngoài vẫn giữ biến count của lần gọi tao_bo_dem. Mẫu này hữu ích cho state cục bộ mà không cần class.

Thực hành

  1. Viết min_max trả tuple, unpack thành hai biến.
  2. Viết hàm chỉ print, gán kết quả và kiểm tra None.
  3. Viết classify với thoát sớm cho ba trường hợp.
  4. Thêm return giữa hàm và quan sát các dòng sau không chạy.
  5. Viết doc_diem trả None khi lỗi, xử lý ở nơi gọi.
  6. Viết hàm trả về một hàm đếm, gọi ba lần.

Lỗi thường gặp

Triệu chứngNguyên nhânCách sửa
Kết quả là NoneHàm không returnThêm return
TypeError với NoneTypeGán kết quả printTrả giá trị thay vì in
Chỉ nhận được giá trị đầureturn dừng hàmGom nhiều giá trị vào tuple/list
Code sau return không chạyreturn đã thoátSắp lại thứ tự hoặc bỏ code chết
ValueError khi unpackSố phần tử không khớpKiểm tra tuple trả về
Không phân biệt lỗi với 0Trả 0 khi lỗiTrả None hoặc ném exception
Hàm trả None ngoài ý muốnNhánh if không có returnRà mọi nhánh

Tóm tắt

  • return kết thúc hàm và trả giá trị; không có thì trả None.
  • Nhiều giá trị thực chất là một tuple, unpack được.
  • print chỉ hiện; return mới cho dùng lại và kiểm thử.
  • Thoát sớm làm code phẳng và rõ.
  • Dùng None cho "không có kết quả", đừng dùng 0 — và luôn kiểm tra ở nơi gọi.

Use ← → to move between lessons