Sửa lỗi 'TypeError: method() takes 1 positional argument but 2 were given' trong Python

beginner🐍 Python2026-05-25| Python 3.x, Tất cả hệ điều hành (Windows, Linux, macOS)

Error Message

TypeError: my_method() takes 1 positional argument but 2 were given
#python#lập trình hướng đối tượng#typeerror#lớp

Giải mã lỗi

Đây là một trong những lỗi phổ biến nhất đối với các lập trình viên đang chuyển sang Lập trình hướng đối tượng trong Python. Bạn gọi một method với một giá trị duy nhất, nhưng Python lại báo rằng bạn đã cung cấp hai. Kết quả traceback thường trông như thế này:

Traceback (most recent call last):
  File "app.py", line 12, in <module>
    account.deposit(500)
TypeError: deposit() takes 1 positional argument but 2 were given

Logic đằng sau đối số "Bị thiếu"

Trong 99% trường hợp, lỗi này xảy ra do bạn quên tham số self trong định nghĩa method của class. Khi bạn gọi một method trên một instance của đối tượng, Python sẽ tự động truyền instance đó vào làm đối số đầu tiên. Python thực hiện việc này ngầm định để các đối tượng có thể theo dõi trạng thái của chính chúng.

Hãy xem ví dụ bị lỗi này:

class BankAccount:
    def deposit(amount): # Thiếu 'self'!
        print(f"Đang nạp ${amount}")

account = BankAccount()
account.deposit(500)

Mặc dù bạn chỉ nhập 500 bên trong dấu ngoặc đơn, Python thực chất thực thi lệnh gọi như sau: BankAccount.deposit(account, 500). Vì hàm của bạn được định nghĩa chỉ chấp nhận một tham số (amount), việc thêm đối tượng account vào đã tạo ra sự sai lệch.

Ba cách để sửa lỗi

1. Cách sửa tiêu chuẩn: Thêm 'self'

Nếu method của bạn cần sửa đổi hoặc đọc dữ liệu từ đối tượng—như thay đổi email của người dùng hoặc số dư ngân hàng—bạn phải bao gồm self. Nó đóng vai trò là một placeholder cho bất kỳ đối tượng cụ thể nào đang gọi hàm.

Mã đã sửa:

class BankAccount:
    def __init__(self):
        self.balance = 0

    # 'self' là tham số đầu tiên, 'amount' là tham số thứ hai
    def deposit(self, amount):
        self.balance += amount
        print(f"Số dư mới: ${self.balance}")

account = BankAccount()
account.deposit(500) # Bây giờ đã hoạt động hoàn hảo

2. Cách sửa tiện ích: Sử dụng @staticmethod

Đôi khi một hàm thuộc về một class để tổ chức mã nguồn, nhưng nó thực sự không cần chạm vào bất kỳ dữ liệu đối tượng nào. Trong những trường hợp này, hãy sử dụng decorator @staticmethod. Điều này thông báo cho Python: "Đừng truyền instance vào hàm này."

class ToolBox:
    @staticmethod
    def convert_to_usd(amount, rate):
        return amount * rate

tb = ToolBox()
# Không có 'self' được truyền vào, vì vậy 2 đối số vẫn là 2 đối số
print(tb.convert_to_usd(100, 1.1))

3. Cách sửa cấp độ Class: Sử dụng @classmethod

Sử dụng @classmethod nếu bạn cần truy cập vào chính class đó thay vì một instance cụ thể. Thay vì self, đối số đầu tiên trở thành cls. Điều này thường thấy khi tạo các method "factory" để tạo ra các đối tượng mới.

class User:
    def __init__(self, name):
        self.name = name

    @classmethod
    def from_guest_account(cls):
        return cls("Khách") # 'cls' tham chiếu đến class User

new_user = User.from_guest_account()

Xác minh giải pháp

Chạy lại script của bạn sau khi thêm self. Nếu bạn đang sửa một instance method, một cách nhanh chóng để xác minh là kiểm tra xem một thuộc tính có thực sự được cập nhật hay không. Đối với ví dụ ngân hàng của chúng ta, việc in account.balance sau khi gọi hàm sẽ xác nhận logic đang hoạt động chính xác. Nếu lỗi vẫn còn, hãy kiểm tra kỹ xem self có thực sự là tham số đầu tiên trong danh sách hay không.

Mẹo chuyên nghiệp để viết code sạch

  • Cái tên là một quy tắc: Về mặt kỹ thuật, bạn có thể gọi self bằng một cái tên khác, như this hoặc me, nhưng bạn không nên làm vậy. Hãy tuân thủ self để đảm bảo các lập trình viên khác có thể đọc mã của bạn mà không gặp khó khăn.
  • Kiểm tra Constructor: Method __init__ là nơi mọi người thường xuyên quên self nhất. Nếu bạn thiếu nó ở đó, mã của bạn sẽ bị lỗi ngay khi bạn cố gắng tạo một đối tượng mới.
  • Lưu ý về Decoration: Nếu bạn thấy mình đang viết một method mà không bao giờ sử dụng self, đó là một dấu hiệu mạnh mẽ cho thấy nó nên là một @staticmethod.

Related Error Notes