Python 3.7には、データクラスと呼ばれる新しい機能が導入されています。
from dataclasses import dataclass
@dataclass
class MyClass:
id: int = 0
name: str = ''
関数パラメーターで型ヒント(注釈)を使用する場合、inspectモジュールを使用して注釈付きの型を簡単に取得できます。データクラスフィールドタイプを取得するにはどうすればよいですか?
from dataclasses import dataclass
@dataclass
class MyClass:
id: int = 0
name: str = ''
myclass = MyClass()
myclass.__annotations__
>> {'id': int, 'name': str}
myclass.__dataclass_fields__
>> {'id': Field(name='id',type=<class 'int'>,default=0,default_factory=<dataclasses._MISSING_TYPE object at 0x0000000004EED668>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD),
'name': Field(name='name',type=<class 'str'>,default='',default_factory=<dataclasses._MISSING_TYPE object at 0x0000000004EED668>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD)}
サイドノートにもあります:
myclass.__dataclass_params__
>>_DataclassParams(init=True,repr=True,eq=True,order=False,unsafe_hash=False,frozen=False)
__annotations__
を調べると生の注釈が得られますが、それらは必ずしもデータクラスのフィールドタイプに対応するとは限りません。 ClassVarやInitVarなどは、フィールドではありませんが、__annotations__
に表示され、継承されたフィールドは表示されません。
代わりに、データクラスで dataclasses.fields
を呼び出し、フィールドオブジェクトを検査します。
field_types = {field.name: field.type for field in fields(MyClass)}
__annotations__
もfields
も文字列注釈を解決しません。文字列注釈を解決したい場合、おそらく最良の方法は typing.get_type_hints
です。 get_type_hints
にはClassVarsとInitVarsが含まれるので、fields
を使用してこれらを除外します。
resolved_hints = typing.get_type_hints(MyClass)
field_names = [field.name for field in fields(MyClass)]
resolved_field_types = {name: resolved_hints[name] for name in field_names}
dataclasses.py は、フィールド注釈を使用して通常のクラスメソッドを生成するためのデコレーターと関数を提供するモジュールです。これは、クラスを処理した後、ユーザー定義フィールドが PEP 526構文の変数注釈 を使用して形成されることを意味します。モジュールの注釈には、__annotations__
としてアクセスできます。
型注釈の実行時効果 によると、注釈付きの型は、__annotations__
属性を介して、または typing.get_type_hints の使用によりアクセスできます。
以下のコードサンプルをご覧ください。
from typing import Dict, ClassVar, get_type_hints
from dataclasses import dataclass
@dataclass
class Starship:
hitpoints: int = 50
get_type_hints(Starship) // {'hitpoints': int}
Starship.__annotations__ // {'hitpoints': int}
dataclasses.__annotations__ // The annotations of the dataclasses module.
get_type_hints(get_type_hints)