7rikazhexde’s tech log

技術的な興味関心、備忘録、アウトプットなどを書いています。

Python mypyエラー(Need type annotation)

前書き

以下プロジェクトでmypyを実行したところ、空のリスト作成で「Need type annotation」のエラーが指摘されたため対策しました。

github.com

エラー指摘内容

リストを代入していますが、型が指定されていない。

error: Need type annotation for "__data" (hint: "__data: List[<type>] = ...")  [var-annotated]

対策

代入するオブジェクトを指定して初期化します。 該当コードはコンストラクタで空のdatarameのオブジェクトを作りましたが、引数を指定してdataframeを作ります。(index、columns、dataは空) 実際は複数のデータを取りうるのでこれで正解かは判断できていませんが、エラーは解消されました。

変更前のコード

class DfManage:
    def __init__(self):
        self.__data = []
        self.__df_data = pd.DataFrame(self.__data)

変更後のコード

        data_list: List[List[int | float | str | None]] = []
        columns_list: List[str] = []
        self.__df_data = pd.DataFrame(data=data_list, columns=columns_list)

self.__df_dataの値確認

        self.__df_data = pd.DataFrame(data=data_list, columns=columns_list)
        print(self.__df_data)
        print(f'values: {self.__df_data.values}')
Empty DataFrame
Columns: [] # 列データはcolumns_listの指定通り空になっています。
Index: [] # 行データに対応してRageIndex型で定義されますが、行データがないので空になってます。
values: [] # valuesは別に確認する必要がありますが、dataパラメータの指定の通りになっています。

<補足>変更後のコードについて

columnsパラメーターはcolumns_list指定で列名は文字列を指定するのでstr型にしました。一方でdataパラメーターは複数の型を取りえるのでそれぞれ記載しました。

空のリストのTypeHint記載のPEP8 484 Type Commentでは、複雑なケースでの型推論を支援するために、以下の形式のコメントを使用することができると記載されています。個人的な理解ではコメントで型推論を補助してくれるというイメージです。

記事を参考に、最初は以下で定義して実際にエラーは解消されましたが、 ふと、int型だけでなぜ警告が消えるか?そもそもlistで取りうる値の型定義を全て書くのが正しいのでは?と思いました。

data_list= [] # type: List[int]

そこで、orで書けば良いのではと思い、実際に書いてみたところ下記でもエラーは消えました。(int定義の時点でエラーは消えてるのでどこまでチェックしてるのかは判断できませんが、意味は伝わると思いますし、この定義が適切だと個人的には思います。)

# 以下のいづれもエラーは表示されない。
from typing import List, Union

data_list= [] # type: List[List[int | float | str | None]]
data_list: List[List[int | float | str | None]] = [] # 対策コードで採用
data_list= [] # type: List[Union[int,float,str,None]]
data_list: List[Union[int, float, str, None]] = []

注意事項

コードはPython最新バージョン対応!より良い型ヒントの書き方を参考にしました。
注意点としてPython 3.9以前では以下の表現はエラーになります。
実際には動作未確認ですが、理由はパイプ(「|」)による表現がPython 3.10以降対象のためです。
なお、mypyのドキュメントを十分に読んでいないので認識に誤りがある可能性がありますのでご注意ください。。(別途ドキュメントは読みたい。)

まとめ

mypyの「Need type annotation」のエラーについて紹介しました。
紹介はしましたが、単純なlistではなく、dataframeなのでやはりどこか引っかかってます。

プログラムは警告もなく、動作は問題ないですが、複数のデータに対する定義には正規のルールはあるのだろうと思います。

Python最新バージョン対応!より良い型ヒントの書き方も非常に参考になりましたが、必要な定義とはいえここまで書かないとだめかと思ってしまいました。(甘えですね。)

別途、mypyのドキュメント含め関連資料は読まないといけないなと感じでいます。

参考記事

以下の記事を参考にさせていただきました。

pandas.DataFrameの構造とその作成方法
https://note.nkmk.me/python-pandas-dataframe-values-columns-index/

空のリストのTypeHint
https://qiita.com/hayata-yamamoto/items/b7d2740305ac22405a2e

型ヒントと typing と mypy https://python.ms/type/#_1-%E3%81%AF%E3%81%97%E3%82%99%E3%82%81%E3%81%AB

Python最新バージョン対応!より良い型ヒントの書き方
https://gihyo.jp/article/2022/09/monthly-python-2209

Unexpected syntax issue: list[1,2,3]
https://discuss.python.org/t/unexpected-syntax-issue-list-1-2-3/21055/14