HOWTO · Python

Python TypeError: 必要な位置引数が 1つありません

Python の TypeError: missing 1 required positional argument: 'self' は、インスタンスメソッドをインスタンスなしで呼ぶと発生します。self の受け渡し、オブジェクトを作る直し方、クラス代入の誤り、@staticmethod の使いどころを解説します。

このページの内容

TypeError: missing 1 required positional argument: 'self' は通常、インスタンスメソッドをインスタンスなしで呼び出したことを示します。def fun(self) のようなメソッドでは、self は慣例として最初に置かれるパラメーターで、オブジェクトを通じてメソッドを呼び出すと Python が値を渡します。これは属性ではなく、パラメーターです。まずオブジェクトを作成し、そのオブジェクトからメソッドを呼び出してください。なお、class はクラスを定義する Python のキーワードです。

「missing 1 required positional argument: ‘self’」の意味

デコレーターなしでクラス内に定義された関数は、インスタンスメソッドです。インスタンスを通じてアクセスすると、Python はそのインスタンスをメソッドにバインドし、self として渡します。同じメソッドにクラスを通じてアクセスした場合、バインドするインスタンスがないため、最初の必須パラメーターが未入力のままになります。

エラーメッセージは、不足しているパラメーターを示しており、メソッドの主な処理に必要な値が不足しているとは限りません。メソッドが def greet(self, name) と定義されている場合、name を渡していても、インスタンスにバインドせずに呼び出すと self が不足することがあります。これは呼び出し時の引数が原因で発生する TypeError です。

クラスからインスタンスメソッドを呼び出すとエラーになる理由

Delft.fun() は、Python にクラスを通じて関数を呼び出すよう指示します。fun が self を必要とする場合は、インスタンスを明示的に渡すか、より分かりやすい方法として、インスタンスからメソッドを呼び出します。よくある関連ミスとして、クラスそのものを変数に代入することがあります。m = Delft ではオブジェクトは作成されません。そのため m.fun() もクラスを通じたメソッド呼び出しとなり、self はバインドされません。

コンストラクターがデータを必要とする場合は、たとえば Delft("Stack") のように、インスタンスの作成時にそのデータを渡します。コンストラクターの括弧を省略してもインスタンスは作成されず、self に値が渡るわけでもありません。クラスは引き続きクラスとして呼び出せます。また、クラスからメソッドにアクセスすること自体が禁止されているわけではありません。呼び出し時の引数をメソッドのパラメーターに合わせる必要があります。

インスタンスを作成して呼び出しを修正する

必要なコンストラクター引数を渡してインスタンスを作成し、変数に格納してから、そのインスタンス上でメソッドを呼び出します。次の自己完結した例が、一般的な書き方です。

このセクションのコードと表示されるラベルや出力は英語のままです。

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

    def fun(self):
        return self.name


m = Delft("Stack")
print(m.fun())

この例は正常に実行され、Stack を出力します。出力される Stack はコード内で指定した名前で、英語のままです。呼び出しによって m が self にバインドされ、メソッドはインスタンスの作成時に保存した名前を返します。

静的メソッドが適している場合

静的メソッドには、インスタンスが自動的に渡されません。クラスとの関連はあるものの、インスタンスの状態を読み取ったり変更したりしない処理には @staticmethod を使います。たとえば、明示的に渡された引数だけを使う書式設定用の補助メソッドをクラスに用意できます。APIに応じて、そのメソッドをクラスまたはインスタンスから呼び出します。

インスタンスメソッドを静的メソッドに変更することは、この TypeError に対する一般的な解決策ではありません。処理が self.name などのオブジェクトごとのデータを使うなら、インスタンスメソッドのままにしてオブジェクトを作成してください。self が使われていないのであれば、そのパラメーターを取り除き、@staticmethod を付けることで、意図した呼び出し方を明確にできます。

メソッドの定義と呼び出し箇所を確認する

メソッドのシグネチャを読み、各必須パラメーターに対応する引数が呼び出しで渡されているか確認します。最初のパラメーターが self なら、クラスや、クラスを参照しているだけの変数ではなく、括弧を付けて作成したオブジェクトからメソッドを呼び出していることを確認してください。また、オブジェクトの作成時にコンストラクターの引数を渡し、メソッドの呼び出し時に通常の引数を渡しているかも確認します。

たとえば、コンストラクターが名前を受け取る場合、m = Delft はクラスを格納しますが、m = Delft("Stack") はインスタンスを作成します。その後の m.fun() では、インスタンスが自動的にバインドされます。メソッドが本当にインスタンスのデータを必要としないなら @staticmethod を検討し、必要とするならインスタンスメソッドのまま呼び出し箇所を修正してください。