静かなる名辞

pythonとプログラミングのこと

2019/03/22:TechAcademyがteratailの質問・回答を盗用していた件
2019/03/26:TechAcademy盗用事件 公式発表と深まる疑念



TypeError: '***' object is not subscriptableの対処法

はじめに

 Pythonを始めてからしばらく時間が経って、ある程度自力で複雑なプログラムを書くようになると、タイトルのようなエラーに遭遇することが多いと思います。

 このエラーが出たときは、たいていはロジックに問題があります。一概に通用する対処法がないので、地道にデバッグをするのが基本です。

 ただ、見慣れない単語が並んでいると思考が停止してしまう人も多いと思います。そこで、大まかな意味と対処法を書いておこうと思います。

原因

 まず、subscriptというのは添字のことです。subscriptionという形にすると添字表記という訳になり、これはlistやdictやstrなどから要素を取り出す、あれのことです。

>>> a = [0, 1, 2]
>>> a[0]  # これが添字表記
0
>>> d["hoge"]  # これも添字表記
0
>>> "hoge"[0]  # これも添字表記
'h'

 Pythonの型には、添字表記に対応しているものと対応していないものがあります。上であげたlist, dict, strはすべて添字表記に対応しています。一方、対応していないものの代表例はint, floatなどの数値型です。

>>> i = 0
>>> i[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not subscriptable
>>> j = 0.1
>>> j[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'float' object is not subscriptable

 「int型/float型のオブジェクトに対して添字表記を使うことはできませんよ」と言ってくれている訳です。これがこのエラーの出る原因です。

対処

 さて、こういうエラーですので、様々なシチュエーションで出てくる可能性がある、ということはなんとなくわかると思います。

 ありがちなのは、listのlist(俗に言う二次元配列)を作ったつもりで、うまくいっていないみたいなケースでしょうか。

>>> lst = [[0,1], 2, 3] # うまく要素が入っていない
>>> for i in range(2):
...     for j in range(2):
...         print(lst[i][j])
... 
0
1
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
TypeError: 'int' object is not subscriptable

 他にも、listみたいなものが返ってくるつもりで書いた関数が実際にはlist以外のものを返していた、みたいなパターンもあるかもしれません。

>>> def pow_lst(lst):
...     result = [x**2 for x in lst]  # returnするのを忘れた
... 
>>> pow_lst([0,1,2,3])[0]  # なにも返さなければNoneというオブジェクトが返る
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not subscriptable

 とにかく色々なケースで出てくるので、対処法としては、

  • エラーメッセージを見て、どの行で出てきたのかを突き止める
  • 添字表記を使おうとしたオブジェクトがどんな型なのかを覚えておく
  • それが自分のコーディング意図と一致しているのかを調べる
  • 場合によっては添字表記を分解し、printデバッグなどをすることで原因を究明する。つまり、たとえば以下のようにする。
# 変更前
result = 何らかの関数など()[0]  # ここでエラーが出たとする

# 変更後
tmp = 何らかの関数など()
print(tmp, type(tmp))
result = tmp[0]

 頑張って検証すればなんとかなることが多い印象ですので、トライしてみてください。

まとめ

 基本的ですが、こういうところで戸惑う人が減るようにと解説を書いてみました。お役に立てれば幸いです。