Pythonデータクラスの使用方法

Pythonのすべてがオブジェクトであるため、ことわざがあります。独自のプロパティとメソッドを使用して独自のカスタムオブジェクトを作成する場合は、Pythonのclassオブジェクトを使用してそれを実現します。ただし、Pythonでクラスを作成するということは、渡されたパラメーターからクラスインスタンスを設定したり、比較演算子などの一般的な関数を作成したりするために、反復的な定型コードを大量に作成することを意味する場合があります。

Python 3.7で導入された(そしてPython 3.6にバックポートされた)データクラスは、クラスの冗長性を減らすための便利な方法を提供します。クラスに渡された引数からプロパティをインスタンス化するなど、クラスで行う一般的なことの多くは、いくつかの基本的な命令に減らすことができます。

Pythonデータクラスの例

Pythonの従来のクラスの簡単な例を次に示します。

クラスの本:

'' 'コレクション内の物理的な本を追跡するためのオブジェクト。' ''

def __init __(self、name:str、weight:float、shelf_id:int = 0):

self.name = name

self.weight =送料を計算するためのグラム単位の重量#

self.shelf_id = Shelf_id

def __repr __(self):

return(f "Book(name = {self.name!r}、

weight = {self.weight!r}、shelf_id = {self.shelf_id!r}) ")

ここでの最大の問題は、渡された各引数を __init__ オブジェクトのプロパティにコピーする方法です。これは、あなただけを扱っている場合はそれほど悪くないです Bookが、何あなたが対処する必要がある場合は Bookshelf、  Library、  Warehouse、など?さらに、手で入力しなければならないコードが多いほど、間違いを犯す可能性が高くなります。

これは、Pythonデータクラスとして実装された同じPythonクラスです。

from dataclasses import dataclass @dataclass class Book: '' 'コレクション内の物理的な本を追跡するためのオブジェクト' '' name:str weight:floatシェルフID:int = 0 

データ クラスで フィールドと呼ばれるプロパティを指定すると、 @dataclass それらを初期化するために必要なすべてのコードが自動的に生成されます。また、各プロパティの型情報も保持さmypyれるため、のようなコードリンターを使用する と、クラスコンストラクターに適切な種類の変数を確実に提供できます。

@dataclass 舞台裏で行うもう1つのこと は、クラス内のいくつかの一般的なdunderメソッドのコードを自動的に作成することです。上記の従来のクラスでは、独自のを作成する必要がありました __repr__。データクラスでは、これは不要です。 @dataclass を生成 __repr__ します。

データクラスが作成されると、通常のクラスと機能的に同じになります。クラス定義を宣言するときのデコレータのオーバーヘッドを最小限に抑えて、データクラスを使用してもパフォーマンスが低下することはありません。

field 関数を使用してPythonデータクラスフィールドをカスタマイズ する

データクラスが機能するデフォルトの方法は、ほとんどのユースケースで問題ないはずです。ただし、データクラスのフィールドの初期化方法を微調整する必要がある場合もあります。これを行うには、field 関数を使用できます 。

データクラスからインポートデータクラス、入力からフィールドインポートリスト@データクラスクラスブック: '' 'コレクション内の物理的なブックを追跡するためのオブジェクト' ''名前:str条件:str =フィールド(比較=偽)重み:フロート=フィールド(デフォルト= 0.0、repr = False)shelf_id:int = 0チャプター:List [str] = field(default_factory = list) 

のインスタンスにデフォルト値を設定すると、指定 fieldしたパラメータに応じてフィールドの設定方法が変わります field。これらは、最も一般的に使用されるオプションですfield (他にもあります)。

  • default:フィールドのデフォルト値を設定します。 a)フィールドの他のパラメータを変更defaultするfieldために使用し、b)その上にあるフィールドにデフォルト値を設定する場合 に使用する必要があります。この場合、をdefault に設定 weight するために使用 し 0.0ます。
  • default_factory:フィールドのデフォルト値として機能するオブジェクトを返す、パラメーターをとらない関数の名前を提供します。この場合、 chapters 空のリストになります。
  • repr:デフォルト(True)は、問題のフィールド__repr__ がデータクラス用に自動生成されたものに表示されるかどうかを制御し ます。この場合、本の重さをに表示したくない __repr__ので、それを repr=False 省略します。
  • compare:デフォルト(True)は、データクラスに対して自動的に生成される比較メソッドのフィールドを含みます。ここではcondition 、2冊の本の比較の一部として使用したくない ので、を設定し compare=Falseます。

デフォルト以外のフィールドが最初に来るように、フィールドの順序を調整する必要があることに注意してください。

__post_init__ Pythonデータクラスの初期化を制御するために使用 します

この時点で、おそらく疑問に思われるでしょう。データ__init__ クラスのメソッドが自動的に生成される場合 、initプロセスを制御して、よりきめ細かい変更を行うにはどうすればよいですか?

__post_init__ メソッドを入力し ます。__post_init__データクラス定義にメソッドを含めると、 フィールドまたはその他のインスタンスデータを変更するための指示を提供できます。

データクラスからインポートデータクラス、入力からのフィールドインポートリスト@データクラスクラスブック: '' 'コレクション内の物理的な本を追跡するためのオブジェクト' ''名前:str weight:float = field(default = 0.0、repr = False)shelf_id:int = field(ini​​t = False)チャプター:List [str] = field(default_factory = list)condition:str = field(default = "Good"、compare = False)def __post_init __(self):if self.condition == "Discarded ":self.shelf_id =なし:self.shelf_id = 0 

この例では 、本の状態がとして初期化__post_init__ さshelf_id れる Noneかどうか を設定するメソッドを作成しました "Discarded"。私たちがどのように使用するか注意 field 初期化するために shelf_id、と渡す init よう False に field。これはshelf_id 、で初期化されないことを意味 し __init__ます。

InitVar Pythonデータクラスの初期化を制御するために使用 します

Pythonデータクラスの設定をカスタマイズする別の方法は、InitVar 型を使用すること です。これは、あなたがに渡されるフィールドを指定することができます __init__ し、その後に __post_init__、しかし、クラスのインスタンスに格納されることはありませんが。

を使用するとInitVar、初期化時にのみ使用されるデータクラスを設定するときにパラメータを取り込むことができます。例:

データクラスからimportdataclass、field、InitVar入力からimport List @dataclass class Book: '' 'コレクション内の物理的な本を追跡するためのオブジェクト' ''名前:str条件:InitVar [str] =なしweight:float = field(default = 0.0、repr = False)shelf_id:int = field(ini​​t = False)chapters:List [str] = field(default_factory = list)def __post_init __(self、condition):if condition == "Discarded":self.shelf_id =その他なし:self.shelf_id = 0 

フィールドのタイプをInitVar (そのサブタイプが実際のフィールドタイプである)に設定する と、その@dataclass フィールドをデータクラスフィールドにしないで__post_init__ 、引数としてデータを渡すように指示さ れ ます。

このバージョンの Book クラスではcondition 、クラスインスタンスにフィールドとして格納していません 。condition初期化フェーズでのみ使用しています。condition に設定されていることがわかった 場合は "Discarded"、に設定 shelf_id し  ますが、クラスインスタンスにNone は保存conditionしません 。

Pythonデータクラスを使用する場合と使用しない場合

データクラスを使用するための一般的なシナリオの1つは、namedtupleの代わりとしてです。データクラスは同じ動作などを提供@dataclass(frozen=True) し、デコレータとして使用するだけで(名前付きタプルのように)不変にすることができます 。

Another possible use case is replacing nested dictionaries, which can be clumsy to work with, with nested instances of dataclasses. If you have a dataclass Library, with a list property shelves, you could use a dataclass ReadingRoom to populate that list, and then add methods to make it easy to access nested items (e.g., a book on a shelf in a particular room).

But not every Python class needs to be a dataclass. If you’re creating a class mainly as a way to group together a bunch of static methods, rather than as a container for data, you don’t need to make it a dataclass. For instance, a common pattern with parsers is to have a class that takes in an abstract syntax tree, walks the tree, and dispatches calls to different methods in the class based on the node type. Because the parser class has very little data of its own, a dataclass isn’t useful here.

How to do more with Python

  • Get started with async in Python
  • How to use asyncio in Python
  • How to use PyInstaller to create Python executables
  • Cython tutorial: How to speed up Python
  • How to install Python the smart way
  • How to manage Python projects with Poetry
  • How to manage Python projects with Pipenv
  • Virtualenvとvenv:Python仮想環境の説明
  • Pythonvirtualenvとvenvはすべきこととすべきでないこと
  • Pythonのスレッド化とサブプロセスの説明
  • Pythonデバッガーの使用方法
  • timeitを使用してPythonコードをプロファイリングする方法
  • cProfileを使用してPythonコードをプロファイリングする方法
  • PythonをJavaScriptに変換する方法(そしてまた元に戻す方法)