0
0

More than 1 year has passed since last update.

dataclassのフィールドとして宣言するには型ヒントが必要

Posted at

環境

  • Python3.11.2

起きたこと

dataclassでクラスTaskを定義しています。フィールドframe_countにはデフォルト値を指定したいです。

In [48]: @dataclass
    ...: class Task:
    ...:     name: str
    ...:     frame_count: int = 10
    ...: 

In [49]: Task("foo", 5)
Out[49]: Task(name='foo', frame_count=5)

frmae_countには10を代入しているので、型ヒントを指定しなくてもmypyはintと推論してくれるだろう」と思い、型アノテーションintを取り除いてみました。
すると、インスタンス生成時に「引数が多すぎる」というTypeErrorが発生しました。

In [51]: @dataclass
    ...: class Task:
    ...:     name: str
    ...:     frame_count = 10
    ...: 

In [52]: Task("foo", 5)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[52], line 1
----> 1 Task("foo", 5)

TypeError: Task.__init__() takes 2 positional arguments but 3 were given

原因

型アノテーションがないとdataclassのフィールドして扱われないから。

dataclasses.dataclassには、以下の様に記載されていました。

dataclass() デコレータは、フィールド を探すためにクラスを検査します。 フィールド は 型アノテーション を持つクラス変数として定義されます。 後述する2つの例外を除き、 dataclass() は変数アノテーションで指定した型を検査しません。

補足:型アノテーションは何でもよい

dataclassのフィールドとして利用するには型ヒントは必須ですが、Pythonは型を検査しないので、どんな型ヒントでもよいです。もちろんmypyなどには怒られると思いますが。

In [53]: @dataclass
    ...: class Task:
    ...:     name: ...
    ...:     frame_count: ... = 10
    ...: 

In [54]: Task("foo", 5)
Out[54]: Task(name='foo', frame_count=5)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0