JP / EN

広告
2024/09/09

型アノテーション:Python3.8以下でTypeError: 'type' object is not subscriptableがでる

タグ:python

Pythonのような動的型付き言語はデータの型を意識しなくても手っ取り早く書ける点が魅力である。 とはいえ大規模プロジェクトでは型がないことで安全なコードがかけなかったり、無用な混乱を招くこともある。 そこでPython3.5から型ヒントの機能が導入された。これは変数や仮引数の定義に型アノテーションを付けて、 どの変数にどの型のデータが入るのかを明示したものである。これに違反した代入などがあれば、静的解析ツールなどで 発見でき安全性が高まる。
    lst: list[int] = [1]  # lstが「intのリスト」であることを明示
    print(list)
  


この型アノテーション、intやstrのような基本型なら簡単なのだがリストや辞書が複雑に絡み合うとややこしくなる。 Python3.9からlist[dict[str]]のような書き方が許されるようになった。 これは型名であるlistdictに[]添え字を付けることができる、新たな文法として追加されている。
Python3.8まではこの文法はなく、このような複合的な型を指定しるためにtypingパッケージからアノテーション専用の型名 ListやDictをインポートして、これを用いて List[Dict[str]]のように書かないといけなかった。 しかもPython3.8以下で前者のlist[dict[str]]のような簡略的な書き方をうっかり使ってしまうと TypeError: 'type' object is not subscriptable というちょっとわかりにくいエラーになってしまうので注意が必要である。最近は新しいPythonに対応したコードが増えてきたので、 なにも考えずに古い環境で動かそうとするとこのエラーに遭遇することが増えてきた。
対処方法としては
  • Pythonのバージョンアップでの対処:Python>=3.9をインストールして使う
  • コード修正による対処:型アノテーション内ではlistやdictの代わりにtyping型名List, Dict等を使うように変更する
ことで回避することができる。

例えば
    lst: list[int] = ["test"]
    print(list)
  
はPython3.9以降での正しいコードであるが、うっかりPython3.8などで実行すると
    $ python typeann.py
    Traceback (most recent call last):
    File "typeann.py", line 1, in <module>
      lst: list[int] = ["test"]
    TypeError: 'type' object is not subscriptable
  
のようにエラーになる。
    from typing import List
    lst: List[int] = [1]
    print(lst)
  
とすればどちらでも動く。ただしこの書き方はPython3.9以降では非推奨であるし、あまり美しくないので やはり可能であれば新しいPythonを使いたいものだ。

おすすめ記事

FastAPI入門:最小構成でとりあえずサーバを立ててみる

Python 内包表記の使い方をマスターする

Pandas 複数のファイルをまとめてDataFrameとして読み込む



このエントリーをはてなブックマークに追加

https://wonderhorn.net/