Câu 1Đoạn code sau in gì?try:
raise ValueError("NG")
print("A")
except ValueError as e:
print(e)
print("B")
Phát sinh ngoại lệ với raise / Lớp ngoại lệ tùy chỉnh
Học cách ném ngoại lệ riêng trong Python với raise và định nghĩa lớp Exception tùy chỉnh để xử lý lỗi chính xác.
Trong bài trước về try / except, chúng ta đã xem phía nhận của một ngoại lệ.
Bài này nói về raise — phía phát sinh, nơi bạn tự phơi bày một ngoại lệ. Khi bạn phát sinh ngoại lệ khi đầu vào không hợp lệ hoặc trạng thái không mong đợi, bên gọi được đảm bảo nhận biết qua try / except.
Cơ bản về raise
Viết raise ExceptionClass("thông điệp") phát sinh ngoại lệ đó ngay lúc đó. Ngay khoảnh khắc raise thực thi, phần còn lại của code bị bỏ qua và điều khiển nhảy đến except khớp.
Thông điệp là tùy chọn, nhưng bao gồm lý do nó thất bại cho phép bên nhận đọc nó ra qua except ... as e.
# Phát sinh một ValueError và bắt nó ở phía nhận
try:
raise ValueError("Tuổi không hợp lệ")
print("không bao giờ đến")
except ValueError as e:
print(f"Đã bắt: {e}")
# Kết quả: Đã bắt: Tuổi không hợp lệ
# Mọi ngoại lệ có sẵn đều dùng được nguyên
# Các lỗi phổ biến: ValueError / TypeError / KeyError / IndexError
Kiểm tra dữ liệu với if + raise
raise được dùng thường xuyên nhất cho kiểm tra đầu vào. Khi một if phát hiện thứ gì đó không hợp lệ, ngay lập tức raise và trả lời gọi về cho bên gọi. Đây là kỹ thuật chuẩn trong hàm (sẽ học sau), nơi phát sinh bên trong một hàm thông báo cho bên gọi về đối số không hợp lệ.
Luồng — đường bình thường chạy qua; đường bất thường phát sinh và dừng — là mẫu cốt lõi cho kiểm tra trong code production.
Kiểm tra đầu vào từng điều kiện một; ngay khoảnh khắc điều gì đó thất bại, raise và dừng. Chỉ khi mọi điều kiện đều qua thì xử lý bình thường mới tiếp tục. Vì raise đầu tiên thắng, thứ tự các kiểm tra đặt ra độ ưu tiên của chúng.
# Kiểm tra giá sản phẩm: 0 hoặc thấp hơn là lỗi
price = -500
try:
if price < 0:
raise ValueError(f"Giá phải là 0 trở lên (nhận được: {price})")
if not isinstance(price, int):
raise TypeError(f"Giá phải là số nguyên (kiểu nhận được: {type(price).__name__})")
print(f"Đã đăng ký: {price}")
except ValueError as e:
print(f"Lỗi giá trị: {e}")
except TypeError as e:
print(f"Lỗi kiểu: {e}")
# Kết quả: Lỗi giá trị: Giá phải là 0 trở lên (nhận được: -500)
Hướng dẫn sơ bộ về chọn ngoại lệ có sẵn nào để raise: dùng ValueError khi giá trị sai, TypeError khi loại (kiểu) không khớp với điều mong đợi, và KeyError / IndexError khi khóa hoặc phần tử đích không tồn tại trong dict hoặc list.
Định nghĩa lớp ngoại lệ tùy chỉnh
Ngoại lệ có sẵn một mình đôi khi khiến khó biết kiểm tra nào đã thất bại. Định nghĩa lớp ngoại lệ của riêng bạn cho phép bạn bắt nó chính xác ở phía except.
Hình dạng là class ErrorName(Exception): với pass (rỗng) làm thân — thế thôi. Chúng ta sẽ học sâu về lớp trong chương lập trình hướng đối tượng sắp tới, nhưng với lớp ngoại lệ, một dòng này là đủ.
# Định nghĩa một ngoại lệ tùy chỉnh (1 dòng là đủ)
class InvalidAgeError(Exception):
pass
class DuplicateUserError(Exception):
pass
registered_users = ["minh", "linh"]
new_user = "minh"
new_age = -1
try:
if new_age < 0:
raise InvalidAgeError(f"Tuổi phải là 0 trở lên: {new_age}")
if new_user in registered_users:
raise DuplicateUserError(f"Đã đăng ký: {new_user}")
print(f"Đã đăng ký: {new_user}")
except InvalidAgeError as e:
print(f"Lỗi tuổi: {e}")
except DuplicateUserError as e:
print(f"Lỗi trùng lặp: {e}")
# Kết quả: Lỗi tuổi: Tuổi phải là 0 trở lên: -1
Ngoại lệ tùy chỉnh đặt Exception làm lớp cha
Exception trong dấu ngoặc đơn chỉ định lớp cha. Đặt Exception ở đó nghĩa là lớp tùy chỉnh của bạn tự động có được các tính năng ngoại lệ tiêu chuẩn — nó có thể mang theo thông điệp, có thể bị bắt bởi except Exception chung, v.v. Bản thân cơ chế cha / con (kế thừa) sẽ được học trong chương lập trình hướng đối tượng, nhưng chỉ một dòng này là đủ để định nghĩa một ngoại lệ.
Trong bài này bạn đã học cách tự phát sinh ngoại lệ với raise, mẫu if + raise cho kiểm tra dữ liệu, và cách định nghĩa lớp ngoại lệ tùy chỉnh đặt Exception làm lớp cha.
Tiếp theo, chúng ta sẽ xem xét def — thứ đã xuất hiện vài lần rồi — như một chủ đề chính và học cách gói gọn và tái sử dụng logic với hàm.
Kiểm tra kiến thức
Hãy trả lời từng câu hỏi một.
Câu 2Ngoại lệ có sẵn nào là phù hợp nhất khi giá trị không hợp lệ?
Câu 3Lợi ích lớn nhất của việc dùng ngoại lệ tùy chỉnh class MyError(Exception): pass là gì?