Tech カテゴリのイメージ

TypeError: 'int' object is not callable の原因と直し方[Python]

これが出たときは、たいてい数分前の自分がやったことが原因になっている。

TypeError: 'int' object is not callable

型の部分はstrだったりlistだったりdictだったりする。意味は共通で、関数ではないものを関数として呼び出している。丸括弧を付けたのに、その名前が指しているのは関数ではなかった、ということになる。

1. 組み込み関数と同じ名前を変数に使った

いちばん多い原因がこれになる。

sum = 0
for x in data:
sum += x
print(sum(data)) # TypeError: 'int' object is not callable

sumという名前を数値で上書きしてしまったので、あとから関数として呼べなくなっている。同じことが起きやすい名前は多い。

sum len max min list dict set str int type id input filter map range next open

対処は変数名を変えるだけになる。

total = 0
for x in data:
total += x
print(sum(data))

厄介なのは、同じセルやスクリプトを再実行するまで気づかないことになる。Jupyterでlist = [1,2,3]と書いてしばらく動き、後半でlist(...)を呼んだ瞬間に落ちる、というのが典型になる。カーネルを再起動すると直るが、原因は残っているのでまた出る。

エディタで組み込み名を使ったときに警告が出るよう設定しておくと予防できる。flake8ならA001A002を出すプラグイン、ruffならbuiltinsの規則が該当する。

2. 掛け算の記号を書き忘れた

数式をそのまま書いたときに起きる。

a = 3
b = 5
print(a(b)) # TypeError
print(2(x + 1)) # TypeError

数学の紙の上では2(x+1)で通じるが、Pythonでは2を関数として呼ぶ意味になる。

print(a * b)
print(2 * (x + 1))

同じ理由で、(a + b)(c + d)のような書き方も落ちる。

3. 関数と戻り値を同じ名前にした

デコレータや代入で、関数そのものを結果で置き換えてしまうパターンになる。

def get_count():
return 42
get_count = get_count() # ここで int になる
print(get_count()) # TypeError

一度目の代入でget_count42になっているので、二度目の呼び出しで落ちる。ループの中でこれをやると、初回だけ通って2回目から落ちるので原因が見えにくい。

4. クラスの属性とメソッドが同名

class Counter:
def __init__(self):
self.count = 0
def count(self): # 属性に上書きされる
return self.count

__init__self.count = 0とした時点で、インスタンスの属性がクラスのメソッドより優先される。obj.count()0()を呼ぶことになる。名前を分ける。

class Counter:
def __init__(self):
self._count = 0
def count(self):
return self._count

5. リストや辞書に丸括弧を使った

添字は角括弧になる。丸括弧は呼び出しになる。

data = [10, 20, 30]
print(data(0)) # TypeError: 'list' object is not callable
print(data[0]) # OK
d = {"a": 1}
print(d("a")) # TypeError: 'dict' object is not callable
print(d["a"]) # OK

多次元配列をa(1, 2)と書いてしまうのも同じ形になる。NumPyやpandasではa[1, 2]が正しい。

原因の特定

どの名前が壊れているかは、型を出せば一発で分かる。

print(type(sum)) # <class 'int'> なら上書きされている

組み込みが上書きされているかどうかは、こう確認できる。

import builtins
name = "sum"
print(name in dir(builtins), type(globals().get(name)))

上書きしてしまった組み込みを元に戻したいときは、その名前を削除すればよい。

del sum # グローバルの sum が消え、組み込みが再び見える

Jupyterでこれをやると、カーネルを再起動せずに復旧できる。

📘 組み込み名との衝突のような落とし穴を一通り知るには、独習Python

まとめ

・呼び出せないものに丸括弧を付けている、というだけのエラー
sum list strなど組み込みと同じ名前を変数に使うのが最頻の原因
・数式の掛け算記号の書き忘れでも起きる。2(x+1)は関数呼び出しになる
・クラスで属性とメソッドを同名にすると、属性が優先されて呼べなくなる
・リストと辞書の添字は角括弧。丸括弧は呼び出し
type(名前)で確認し、上書きした組み込みはdelで元に戻せる

※本記事にはアフィリエイト広告を含みます。