はじめに
Python3.10でdataclassに新たに追加された引数について少し調べたので、まとめてみた。
参考文献
dataclassとは
Python3.7より標準ライブラリとして搭載された、データを格納するためのクラスが簡単に定義可能となったモジュール。
dataclassの簡単な使用方法は以下。
from dataclasses import dataclass
@dataclass
class User:
name: str
age:int
user1 = User('Jun', 20)
print(user1)
# User(name='Jun', age=20)
dataclass()の引数
Python3.10現在、dataclass()に使用できる引数には以下のようなものがある。
- init
- repr
- eq
- order
- unsafe_hash
- frozen
- match_args (3.10で新たに追加)
- kw_only (3.10で新たに追加)
- slots (3.10で新たに追加)
Python3.10で新たに追加されたものは、match_args
, kw_only
, slots
の3種類である。この記事では、これらについてを簡単にまとめる。
match_args
macth_args = True
と指定したとき、クラス変数 __match_args__
を生成する。
__match_args__
によって、Python3.10で導入されたmatch, case文での条件分岐時に、クラス変数としてキーワード指定することなくタプルで条件指定が可能となる。
通常のclassでのmatch, case文では、
class User:
def __init__(self, name: str, age: int):
self.name = name
self.age = age
user1 = User('Jun', 20)
match user1:
case User(name='Bob', age=34):
print('name: Bob, age: 34')
case User(name='Jun', age=20):
print('name: Jun, age: 20')
# name: Jun, age: 20
と、case文内において、User(name='Bob', age=34)
と、キーワードを指定する必要がある。
以下のように、__match_args__
を定義すると
class User:
__match_args__ = 'name', 'age'
def __init__(self, name: str, age: int):
self.name = name
self.age = age
user1 = User('Jun', 20)
match user1:
case User('Bob', 34):
print('name: Bob, age: 34')
case User('Jun', 20):
print('name: Jun, age: 20')
# name: Jun, age: 20
User('Bob', 34)
のように、キーワード指定をする必要がなくなる。
@dataclass(match_args=True)
とすると、この __match_args__
を自動で生成してくれる。
from dataclasses import dataclass
@dataclass(match_args=True)
class User:
name: str
age: int
user1 = User('Jun', 20)
match user1:
case User('Bob', 34):
print('name: Bob, age: 34')
case User('Jun', 20):
print('name: Jun, age: 20')
# name: Jun, age: 20
kw_only
kw_only = True
と指定したとき、全てのフィールドをキーワード指定専用にすることができる。
from dataclasses import dataclass
@dataclass(kw_only=True)
class User:
name: str
age: int
user1 = User(name='Jun', age=20)
print(user1)
# User(name='Jun', age=20)
以下のようにキーワード指定をしないと、エラーになる。
from dataclasses import dataclass
@dataclass(kw_only=True)
class User:
name: str
age: int
user1 = User('Jun', 20) # TypeError: User.__init__() takes 1 positional argument but 3 were given
slots
slots = True
と指定したとき、クラス変数 __slots__
を生成する。
__slots__
とは、固定長のクラス変数保管用配列を指定するクラス変数である。
Pythonでは、クラスのフィールドを保持するためにデフォルトでは辞書が用いられている。
from dataclasses import dataclass
@dataclass()
class User:
name: str
age: int
user1 = User('Jun', 20)
print(user1.__dict__)
# {'name': 'Jun', 'age': 20}
フィールドを辞書で保持することのデメリットとして、
- 間違った代入が起きてしまう
ことが挙げられる。
例えば、以下のように、name
に値を再代入しようとした際に、誤って nama
と記述してしまったとする。
from dataclasses import dataclass
@dataclass()
class User:
name: str
age: int
user1 = User('Jun', 20)
user1.nama = 'Haru'
print(user1.__dict__)
# {'name': 'Jun', 'age': 20, 'nama': 'Haru'}
このとき、name
への再代入は行われず、nama
への代入が行われてしまう。
これを防ぐのが、__slots__
である。
from dataclasses import dataclass
@dataclass()
class User:
name: str
age: int
__slots__ = ['name', 'age']
user1 = User('Jun', 20)
user1.nama = 'Haru' # AttributeError: 'User' object has no attribute 'nama'
上記のように、__slots__
を定義すると、フィールドの名前を定義することが可能になるので誤った代入が起きる心配はなくなる。
また、__slots__
を定義すると、フィールドが固定長配列に格納されるので、処理速度が速くなるというメリットもあるようだ。(参考:https://www.python.jp/news/wnpython310/dataclass-with-slots.html)
from dataclasses import dataclass
@dataclass(slots=True)
class User:
name: str
age: int
user1 = User('Jun', 20)
print(user1.__slots__)
# ('name', 'age')
以上のようにdataclassでは、slots = True
とすると、__slots__
を自動的に生成してくれる。
まとめ
今回は、Python3.10でdataclassに新たに追加された引数について簡単にまとめてみた。
特に、 slots
は便利だと感じたので、今後は積極的に使用していこうと思った。