【Python】TypeError: 関数名 takes 0 positional arguments but 1 was givenの原因と解決方法

時計 2020.05.28 / 時計

TypeError: 関数名 takes 0 positional arguments but 1 was givenの原因と解決方法

Pythonでプログラムを作成していると必ず一度は遭遇するエラーの1つ、

TypeError: 関数名 takes 0 positional arguments but 1 was given

今回はこのエラーの原因と解決方法を解説します。

このエラーが発生するパターンには3つあります。(もしくはもっとあるかもしれませんが、この3つしか今は知らないです)

パターンによってこのエラー内の数値は変更しますが、それ以外は同じです。

私は最後に紹介する3つ目のパターンで長時間はまった経験があります。

私のように無駄に長い時間をエラー解決に費やさないようにしてくださいね。

引数の数が異なるとき

関数が要求する引数の数と実際に関数呼び出しの際に渡している引数の数が異なるとこのTypeErrorが発生します。

以下のサンプルプログラムを使って詳しく説明します。

def tasu(x, y):
	return x+y
print(tasu(5, 4, 3))

このPythonプログラムを実行すると、プログラムは実行されずに以下のエラーが表示されます。

tasu() takes 2 positional arguments but 3 were given

このエラーは、「tasu()は2つの固定引数を取る、しかし3つが与えられた」という意味です。

IT用語の確認

エラー内で使われている英単語[argument]は引数という意味です。ちなみに変数は[variable]です。

このエラー内容からわかるように、関数が要求する引数の数と実際に渡した引数の数が異なるとこのエラーが発生します。

これがこのエラーの根本的な意味合いです。

今回のサンプルプログラムでは、tasu()関数は2つの引数を要求しているが、実際には3つの値を渡していることがわかります。

このパターンであればすぐに気づくことができますが、以下紹介する2パターンはもう少し難しくなります。

クラス内で外部関数を使うとき

クラスを作成し、その中でクラスの外で定義している関数を呼び出したときに、このTypeErrorが発生することがあります。

以下のサンプルプログラムをみてください。

class Office54:
	def recommend():
		print(‘It is a great site!’)
o = Office54()
o.recommend()

このプログラムを実行すると以下のエラーが出ます。

TypeError: recommend() takes 0 positional arguments but 1 was given

このエラーは、「recommend()は0個の固定引数を取る、しかし1つが与えられた」という意味です。

しかしサンプルプログラムを見る限り、呼び出し元のo.recommend()はなにも値を渡していませんよね。

実はクラス内の関数を呼び出す際にselfが引数の1つ目としてクラス内関数に渡されます。

selfはクラス自身を指しており、クラス内の関数には引数selfを受け取る記述が必要になります。

class Office54:
	def recommend(self):
		print(‘It is a great site!’)
o = Office54()
o.recommend()

これによりエラーが表示されなくなり、プログラムを実行することができます。

このPythonのselfを受け取る必要がある仕様により、たくさんの時間を無駄にしたプログラマーは少なくないはずです。

関数の中で(バインドなどされた)関数を呼ぶとき

これが私が以前にはまったことがあるパターンです。

tkinterでプログラムを作っている際にTypeErrorが発生しました。

以下に私がはまったプログラムの一部です。

def text():
    print('click')
def click():
    canvas.bind("<Button-1>", text)

あるclick()関数が紐づいたButtonを押すとCanvasに左クリックで起動するtext()関数がバインドされます。

そしてCanvasを左クリックすればtext()関数が起動して中身が実行されるはずでしたが、以下のエラーが表示されました。

text() takes 0 positional arguments but 1 was given

原因を調べたのですがよくわからず、パターン1とパターン2については知っていたので、以下のように書き換えました。

def text(self):
    print('click')
def click():
    canvas.bind("<Button-1>", text)

これで問題なくプログラムは実行されました。

ということは、関数の中でバインドなどされた関数を呼び出すときはselfがその関数に渡されるということです。

渡す引数が少なかった場合のエラー

今回紹介したエラー「TypeError: 関数名 takes 0 positional arguments but 1 was given」は、関数に渡した引数が要求よりも多い場合に発生します。

では逆に渡した引数が、関数が要求している引数よりも少なかった場合はどうなるのか?

その場合に発生するエラーについては以下記事をご参照ください。

まとめ

Pythonでプログラムを作っていると未知のエラーと遭遇することが多々あります。

いわゆる「未知との遭遇」ですね。

今後も未知との遭遇があったら、記事にして共有していければと思います。