Mô tả lỗi
Script Python của bạn bị crash với thông báo:
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Python phát hiện bạn dùng + giữa một số nguyên và một chuỗi nên từ chối thực thi. Khác với JavaScript hay PHP, Python không bao giờ tự động ép kiểu ngầm — bạn phải làm rõ ràng. Đây thực ra là tính năng, không phải lỗi. Nó ngăn chặn cả một loạt lỗi hỏng dữ liệu khó phát hiện.
Các tình huống thường gặp
Tình huống 1: Trộn lẫn input người dùng với số
input() luôn trả về chuỗi — kể cả khi người dùng nhập 25:
age = input("Nhập tuổi của bạn: ") # trả về '25', không phải 25
years = 10
print("Sau 10 năm nữa bạn sẽ " + age + years) # ❌ TypeError
Tình huống 2: Ghép chuỗi với biến số
count = 42
message = "Tổng số mục: " + count # ❌ TypeError
Tình huống 3: Dữ liệu từ file, API hoặc database
File CSV, JSON response và các driver database thường trả về các giá trị trông như số nhưng thực ra là chuỗi. Tình huống này khiến cả lập trình viên có kinh nghiệm cũng bị nhầm:
row = {"price": "99", "tax": "8"}
total = row["price"] + row["tax"] # trả về "998", không phải 107 — nối chuỗi, không phải phép tính
Cách sửa nhanh
Cách 1: Chuyển số nguyên sang chuỗi để nối
Đang xây dựng thông báo? Bọc số trong str():
count = 42
message = "Tổng số mục: " + str(count) # ✅ "Tổng số mục: 42"
Cách 2: Chuyển chuỗi sang số nguyên để tính toán
Đang làm toán? Chuyển đổi bằng int() trước:
age = input("Nhập tuổi của bạn: ") # "25"
years = 10
future_age = int(age) + years # ✅ 35
Cách 3: Dùng f-string (cách gọn nhất)
F-string nhúng giá trị trực tiếp mà không cần chuyển đổi thủ công. Đây là cách Python hiện đại:
count = 42
message = f"Tổng số mục: {count}" # ✅ không cần str()
age = int(input("Nhập tuổi của bạn: "))
years = 10
print(f"Sau 10 năm nữa bạn sẽ {age + years} tuổi")
Giải pháp triệt để: Xử lý chuyển đổi kiểu an toàn
Luôn chuyển đổi input() ngay lập tức
Lỗi mà hầu hết người mới mắc phải: đọc input dưới dạng chuỗi rồi quên chuyển đổi hai mươi dòng sau đó. Hãy chuyển đổi ngay tại nguồn:
# Không tốt — dễ quên
raw = input("Nhập giá: ")
# ... 20 dòng code tiếp theo ...
total = raw + 5 # ❌ TypeError, xa chỗ lỗi bắt đầu
# Tốt — chuyển đổi ngay tại chỗ
price = float(input("Nhập giá: ")) # ✅ price là float từ đây
total = price + 5 # ✅ kết quả là 10.0 nếu input là "5"
Validate và chuyển đổi dữ liệu từ nguồn ngoài
Bọc phần chuyển đổi vào một hàm helper khi dữ liệu đến từ ngoài tầm kiểm soát của bạn:
def safe_add(a, b):
try:
return int(a) + int(b)
except (ValueError, TypeError) as e:
raise TypeError(f"Không thể cộng {type(a).__name__} và {type(b).__name__}: {e}")
row = {"price": "99", "tax": "8"}
total = safe_add(row["price"], row["tax"]) # ✅ 107
Dùng f-string thay vì + để ghép chuỗi
Ghép chuỗi bằng + sẽ lỗi ngay khi bất kỳ giá trị nào chưa phải chuỗi. F-string thì không bao giờ vậy:
# Dễ vỡ — mỗi biến phải bọc str() thủ công
result = "Điểm: " + str(score) + "/" + str(total) + " (" + str(pct) + "%)"
# Vững chắc — kiểu dữ liệu không quan trọng
result = f"Điểm: {score}/{total} ({pct}%)"
Debug: Tìm chỗ xảy ra lỗi kiểu dữ liệu
Khi lỗi xảy ra sâu bên trong code, không phải lúc nào cũng rõ biến nào đang sai kiểu. Dùng type() để kiểm tra:
a = get_value_from_somewhere()
b = get_another_value()
print(type(a), type(b)) # ví dụ:
result = a + b
Tốt hơn nữa, thêm assertion để bắt sự không khớp trước khi chúng gây lỗi khó hiểu ở chỗ khác:
assert isinstance(a, int), f"Mong đợi int, nhận được {type(a).__name__}: {a!r}"
assert isinstance(b, int), f"Mong đợi int, nhận được {type(b).__name__}: {b!r}"
Kiểm tra sau khi sửa
Chạy đoạn code này để xác nhận mọi thứ hoạt động đúng:
# Phải bắt được lỗi, không crash
try:
result = 10 + "5"
except TypeError as e:
print(f"Đã bắt lỗi: {e}")
# Phải in ra 15
result = 10 + int("5")
print(result) # 15
# Phải in ra "Value: 10"
result = "Value: " + str(10)
print(result) # Value: 10
Cả hai đoạn đã sửa đều phải in ra kết quả đúng mà không ném ra ngoại lệ nào.
Tóm tắt
- Dùng
str(number)khi xây dựng chuỗi có chứa số. - Dùng
int(string)hoặcfloat(string)khi tính toán với giá trị chuỗi. - Ưu tiên f-string hơn nối chuỗi bằng
+— chúng xử lý kiểu dữ liệu tự động. - Chuyển đổi giá trị từ
input(), file hoặc API ngay khi đọc, đừng để đến nhiều dòng code sau.

