Lỗi Gì Xảy Ra
Script của bạn vừa chết lúc 2 giờ sáng với lỗi này:
TypeError: 'str' object is not callable
Traceback trỏ đến một dòng trông có vẻ hoàn toàn ổn. Thủ phạm thực sự thường nằm ở một cấp trên — thứ bạn đặt tên sai ở phần trước trong file.
Nguyên Nhân Thực Sự Gây Ra Lỗi
Python ném lỗi này khi bạn đặt () sau thứ gì đó là chuỗi, không phải hàm. Ba tình huống sau chiếm 95% các trường hợp:
1. Bạn Ghi Đè một Built-in
str = "giá trị nào đó" # Bạn đặt tên biến là 'str'
result = str(123) # Python giờ nghĩ str là chuỗi của bạn, không phải built-in
# TypeError: 'str' object is not callable
2. Bạn Gọi Biến Chuỗi Như Một Hàm
formatter = "Xin chào, {}"
output = formatter("thế giới") # formatter là chuỗi, không phải hàm
# TypeError: 'str' object is not callable
3. Thuộc Tính Class Ghi Đè Một Method
class Report:
def __init__(self):
self.generate = "đang chờ" # Dòng này ghi đè method bên dưới
def generate(self):
return "dữ liệu báo cáo"
r = Report()
r.generate() # TypeError: 'str' object is not callable
Chẩn Đoán Nhanh
Thêm hai dòng này ngay trước dòng bị lỗi:
print(type(your_variable)) # <class 'str'> = đó là thủ phạm
print(callable(your_variable)) # False = không thể gọi được
Hoặc dùng debugger để kiểm tra từng bước:
import pdb; pdb.set_trace()
# Trong prompt: print(type(the_thing_you_called))
Cách Sửa 1: Đổi Tên Biến Bị Ghi Đè
Built-in của Python không phải là từ khóa dành riêng. Python sẽ không ngăn bạn đặt tên biến là str hay list — nó chỉ âm thầm phá vỡ mọi thứ dựa vào built-in thực sự.
Lỗi:
str = "giá trị chuỗi của tôi"
num = 42
result = str(num) # Bị lỗi — str giờ là biến của bạn
Đã sửa:
my_str = "giá trị chuỗi của tôi"
num = 42
result = str(num) # Hoạt động — str() là built-in trở lại
Hãy cẩn thận với các built-in khác mà bạn có thể vô tình dùng lại: list, dict, id, input, print, type, format, filter, map. Tất cả đều là tên biến hợp lệ. Nhưng không cái nào nên dùng làm tên biến.
Khôi Phục Built-in Bị Ghi Đè Trong Phiên
Đang ở trong interactive shell sau khi chạy str = "thứ gì đó"? Xóa biến đó đi:
del str # Xóa biến của bạn
str(123) # '123' — built-in được khôi phục
Cách Sửa 2: Dùng .format() hoặc f-string Thay Vì Gọi Như Hàm
Template chuỗi không được gọi như hàm — chúng dùng .format() hoặc f-string.
Lỗi:
greeting = "Xin chào, {}"
message = greeting("Alice") # TypeError
Đã sửa:
# Cách 1: .format()
message = greeting.format("Alice")
# Cách 2: f-string (gọn hơn)
name = "Alice"
message = f"Xin chào, {name}"
Nó đáng lẽ phải là một hàm thực sự ngay từ đầu? Định nghĩa đúng cách:
def greeting(name):
return f"Xin chào, {name}"
message = greeting("Alice") # Hoạt động
Cách Sửa 3: Đổi Tên Thuộc Tính Class Bị Xung Đột
Việc gán self.generate = "đang chờ" trong __init__ âm thầm thay thế method generate trên instance đó. Python tìm kiếm thuộc tính instance trước method class — nên chuỗi của bạn thắng, và sau đó thất bại khi được gọi.
Lỗi:
class Report:
def __init__(self):
self.generate = "đang chờ" # Phá hủy method
def generate(self):
return "dữ liệu báo cáo"
Đã sửa:
class Report:
def __init__(self):
self.status = "đang chờ" # Tên khác, không xung đột
def generate(self):
return "dữ liệu báo cáo"
r = Report()
r.generate() # Hoạt động
Xác Nhận Đã Sửa Xong
Xác nhận mọi thứ đã trở lại bình thường trong Python shell:
>>> str(42)
'42'
>>> callable(str)
True
>>> callable("một chuỗi nào đó")
False
Đang chạy trong một module đã được import? Khởi động lại tiến trình Python. Biến cũ có thể vẫn còn tồn tại trong namespace của module từ lần import trước.
Ngăn Điều Này Xảy Ra Lần Nữa
Cài một linter. Cả pylint và flake8 đều phát hiện việc ghi đè built-in trước khi đến production:
pip install pylint
pylint your_script.py
# W0622: Redefining built-in 'str' (redefined-builtin)
VS Code với Pylance và PyCharm đều highlight các xung đột này ngay khi bạn gõ. Cài đặt một lần — bạn sẽ phát hiện loại bug này trong vài giây, không phải lúc 2 giờ sáng.
- pylint: cảnh báo
W0622 redefined-builtin - flake8 + flake8-builtins: cảnh báo
A001 variable is shadowing a Python builtin - Pyright / Pylance: gạch chân tên bị xung đột trong editor
Hầu như luôn là do xung đột tên. Tìm thứ bạn đặt tên trùng với một hàm, đổi tên lại, và lỗi TypeError: 'str' object is not callable sẽ biến mất.

