エラーの解読
これは、Pythonでオブジェクト指向プログラミング(OOP)に移行する開発者が最も頻繁に遭遇する「落とし穴」の1つです。引数を1つだけ渡してメソッドを呼び出したのに、Pythonは2つ渡されたと主張します。トレースバックは通常、以下のようになります。
Traceback (most recent call last):
File "app.py", line 12, in <module>
account.deposit(500)
TypeError: deposit() は 1 つの位置引数を受け取りますが、2 つ与えられました
「足りない」引数の背後にある論理
99%のケースで、このエラーはクラスメソッドの定義に self パラメータを入れ忘れたことが原因で発生します。オブジェクトのインスタンスに対してメソッドを呼び出すと、Pythonはそのインスタンスを自動的に最初の引数として渡します。これは、オブジェクトが自身の状態を追跡できるように、舞台裏で行われている処理です。
こちらの間違った例を見てみましょう:
class BankAccount:
def deposit(amount): # 'self' がありません!
print(f"{amount} を入金中")
account = BankAccount()
account.deposit(500)
括弧の中に 500 とだけ入力しても、Pythonは実際には BankAccount.deposit(account, 500) のように呼び出しを実行します。関数が1つの引数(amount)のみを受け取るように定義されているため、account オブジェクトが追加されることで不一致が生じます。
3つの解決方法
1. 標準的な修正:'self' を追加する
メソッドがユーザーのメールアドレスや銀行残高の変更など、オブジェクトのデータを変更または読み取る必要がある場合は、self を含める必要があります。これは、関数を呼び出している特定のオブジェクトのプレースホルダーとして機能します。
修正後のコード:
class BankAccount:
def __init__(self):
self.balance = 0
# 'self' が最初のパラメータ、 'amount' が2番目です
def deposit(self, amount):
self.balance += amount
print(f"新しい残高: ${self.balance}")
account = BankAccount()
account.deposit(500) # これで正常に動作します
2. ユーティリティ的な修正:@staticmethod を使用する
整理のためにクラス内に配置されているものの、実際にはオブジェクトのデータに触れる必要がない関数もあります。このような場合は、@staticmethod デコレータを使用します。これにより、Pythonに「この関数にはインスタンスを渡さないでください」と伝えます。
class ToolBox:
@staticmethod
def convert_to_usd(amount, rate):
return amount * rate
tb = ToolBox()
# 'self' は渡されないため、引数は2つのままです
print(tb.convert_to_usd(100, 1.1))
3. クラスレベルの修正:@classmethod を使用する
特定のインスタンスではなく、クラス自体にアクセスする必要がある場合は @classmethod を使用します。self の代わりに、最初の引数は cls になります。これは、新しいオブジェクトを生成する「ファクトリ」メソッドを作成する際によく使われます。
class User:
def __init__(self, name):
self.name = name
@classmethod
def from_guest_account(cls):
return cls("ゲスト") # 'cls' は User クラスを参照します
new_user = User.from_guest_account()
解決策の検証
self を追加した後、スクリプトを再実行してください。インスタンスメソッドを修正している場合、属性が実際に更新されたか確認するのが手っ取り早い検証方法です。銀行の例であれば、呼び出し後に account.balance を表示して、ロジックが正しく流れていることを確認します。エラーが消えない場合は、self が本当にパラメータリストの最初にあるか再確認してください。
クリーンなコードのためのヒント
- 名前は慣習: 技術的には
selfをthisやmeと呼ぶこともできますが、そうすべきではありません。他の開発者が混乱せずにコードを読めるよう、selfを使い続けましょう。 - コンストラクタを確認:
__init__メソッドは、最もselfを忘れやすい場所です。ここで忘れると、新しいオブジェクトを作成しようとした瞬間にコードがクラッシュします。 - デコレータを意識する: もし一度も
selfを使わないメソッドを書いているなら、それは@staticmethodにすべきであるという強いサインです。

