はじめに
こんにちは。フルサポート開発チームのshi_maです。
先日動物園に行ったらワオキツネザルから勢いよく餌を投げつけられました。好意的に解釈するとおそらくプレゼントだったのでしょう!
今回はcattrsという便利なPythonのライブラリを紹介します。
cattrsとは
GitHub: https://github.com/python-attrs/cattrs
公式ドキュメント: https://cattrs.readthedocs.io/en/latest/index.html
表題に書いた通り、cattrsとはデータを任意の形式に構造化できるPythonのライブラリです。
たとえば、CSVから読み込んだデータやJSON形式で受け取ったリクエストデータをPythonのclassに変換して扱いやすくできます。
実際にcattrsがどんな動きをするのか見ていきましょう。
使い方
今回利用するcattrsのバージョンは1.10.0です。
まずはstructureという関数を利用してデータを構造化します。
import cattr
print(cattr.structure([1.0, 2, '3'], tuple[int, int, int]))
> (1, 2, 3)
structure関数は第一引数に構造化するオブジェクト、第二引数はどのような構造にするのか表す型を定義します。
上記の例ではfloat、int、stringの3種類の値を持つリストが、3つのint値からなるタプルに変わりました。
次はdictをカスタムクラスに変換します。
Pythonにはカスタムクラスをシンプルに記述できるattrsという人気のライブラリがあるのですが、cattrsはこのライブラリとあわせて使うことを意識して作られており、併用するがオススメです。
なお逆にカスタムクラスをdictに変換したい時はunstructure関数が使えます。
import cattr
from attr import frozen
@frozen
class User:
name: str
age: int
user_dict = {
'name': 'Taro',
'age': 30,
}
# structure関数でdictをUserクラスに
user = cattr.structure(user_dict, User)
print(user.name)
> Taro
# unstructure関数でUserクラスをdictに
>>> print(cattr.unstructure(user))
{'name': 'Taro', 'age': 30}
もちろんdictをattrsを利用していない素のカスタムクラスに変えることも可能です。
その場合は、register_structure_hookという関数を使い、コンバータークラスに構造化のフックを登録する必要があります。
import cattr
class User:
def __init__(self, name, age):
self.name = name
self.age = age
cattr.register_structure_hook(User, lambda d, t: User(**d))
user_dict = {
'name': 'Taro',
'age': 30,
}
user = cattr.structure(user_dict, User)
print(user.name)
> Taro
もしregister_structure_hook関数の処理がないと以下のようなエラーが起きます。
cattr.errors.StructureHandlerNotFoundError: Unsupported type: . Register a structure hook for it.
最後にCSVから読み込んだデータをPythonのカスタムクラスに変換してみます。
# animals.csv
# name,group
# 'ワオキツネザル','哺乳類'
# 'ウグイス','鳥類'
# 'マグロ','魚類'
import csv
import cattr
from attr import frozen
@frozen
class Animal:
name: str
group: str
@frozen
class Zoo:
animals: list[Animal]
with open('animals.csv', 'r') as f:
zoo = cattr.structure({'animals': list(csv.DictReader(f))}, Zoo)
for animal in zoo.animals:
print(animal)
> Animal(name='ワオキツネザル', group='哺乳類')
> Animal(name='ウグイス', group='鳥類')
> Animal(name='マグロ', group='魚類')
終わりに
今回はcattrsの基本的な使い方をご紹介しました。
現時点では少々マイナーなライブラリですが、attrsと併用するとかなり使い勝手が良いので、Pythonを書かれている方はぜひお試しください!