nikkie-ftnextの日記

イベントレポートや読書メモを発信

CSVファイルの行からデータクラスのインスタンスを作る(map / starmap / 辞書版自作doublestarmap)

はじめに

ういっす✌️ nikkieです。

先日、CSVファイルの行を種々のデータ型に変換する実装を一覧にしました。

その中でデータクラスのインスタンスへの変換について、いろんなやり方があると気づいたので一覧にします。

目次

前提

CSV形式のファイルを読み込んで、行を各種データ型に変換する題材を引き続き考えていきます。
このエントリでは、CSV形式の行からデータクラスのインスタンスを作る方法に集中します。

読み込むCSVsome.csv)は以下です。

name,price
apple,1000
banana,500

Python 3.10.9で動作確認しました

csv.readerが返す要素(リスト)から作る

CSVファイルの行はリストで表されます。

['apple', '1000']

mapを使う

データクラスのインスタンスを作るメソッド(ファクトリメソッド)をcsv.readerが返すリスト(行)1つ1つにmapで適用します。
https://docs.python.org/ja/3/library/functions.html#map

ファクトリメソッドは行を表すリストを受け取ります(1引数)。
リストをまずアンパックしてから、インスタンスを返す実装にしました。

itertools.starmapを使う

こちらは先日のエントリで示したコードと同一です。

starmapmapと違って、シーケンスをアンパックした状態でファクトリメソッドに渡します(位置引数渡し)。
https://docs.python.org/ja/3/library/itertools.html#itertools.starmap
つまり、ファクトリメソッドはシーケンス1つを受け取る引数ではなく、シーケンスの要素数だけの引数(ここでは2引数)を持ちます。

csv.DictReaderが返す要素(辞書)から作る

CSVファイルの行は辞書で表されます。

{'name': 'apple', 'price': '1000'}

mapを使う

ファクトリメソッドは行を表す辞書を受け取ります(1引数)。
キーを使って辞書の値にアクセスしてインスタンスを作ります。

「書きやすくなるかな」とTypedDictも使ってみました1
VS Codeを使っているのですが、辞書のキーがサジェストされるのはありがたいですね。

itertools.starmap相当を自作して使う

csv.reader(行がリスト)のときのstarmapのように、行が辞書のときのstarmap的なものを自作しました。
辞書をアンパックしてキーワード引数として渡してくれるstarmapです(命名doublestarmap)。 どなたか実装していそうですが、調べきれなかったので、starmapをもとに自作しました。

doublestarmapを使うと、ファクトリメソッドは(辞書を受け取る1引数ではなく、)辞書の長さだけの引数を持ちます。

終わりに

CSVファイルの行からデータクラスのインスタンスを作る方法を洗い出しました。

データクラスのインスタンスを作るメソッドの引数の数に注目すると

  • 1引数:行を表すリストや辞書
    • 組み込み関数mapと使う
  • 複数の引数(行に含まれる要素と同じだけの引数)
    • リストの場合はitertools.starmapを使う
    • 辞書の場合はstarmap相当の関数を自作した(doublestarmap

となりました。
mapstarmapの違いもつかめたように感じます。


  1. ロバストPython』に教えてもらいました。