15. 振り返り2¶
15.2. 文字列・リスト・辞書・集合に対する操作¶
全ての操作を覚えておく必要はない。代表的な操作(オブジェクトの作成、要素の追加・削除・検索)については身につけておき、必要に応じて調べて使えるようになろう。
15.3. ファイル入出力¶
できる限りwith構文を用い、ファイルハンドラを利用するブロックを限定するように書こう。with構文でブロックを明示することによりcloseし忘れること無く正常にプログラムを終了することができる。
15.4. 第三者が利用しやすく、読みやすくする工夫¶
型ヒント・docstring・doctestを組み合わせることで利用しやすい関数設計を検討しよう。なお、授業の課題で提出するコードは一度書いたらそれで終わりとなることが多いかもしれないが、卒業研究や就職後は 使われ続けるコード を書くことになる。その際には第三者にとっても読み書きしやすいコードが求められるし、何より自身が書いたコードであっても数週間後には何故そのような実装をしているのか分からなくなってしまうことが珍しくない。もしドキュメント等が全く存在しないなら、バグが見つかった際や新規機能を追加したくなった場合にはその都度全てのコードを読み解かなくてはならず、極めて不合理的だ。「使われ続けるコード」を意識するためにも型ヒント・docstring・doctestを書くようにしよう。
15.5. KISS原則&DRY原則¶
まずは想定通りに動作するコードを書くことを最優先しよう。その次のステップとして、コードの読みやすさを意識してみよう。コードは、授業課題のようなケースを除いて一般的には中長期的に使い続けることが多い。利用者は自分だけとは限らないし、自分だけであったとしても数週間前に書いたコードを思い出すのは困難であることも少なくない。これらを手助けするためにドキュメンテーションやコメントといった手段もあるが、これらに加えて「読みやすいコード(readable code)」がある。
読みやすいコードなら、どこかに潜在的なバグがありそうな場合に気づきやすく、またそうでなくともデバッグしやすいことが多い。つまり「使い続ける」ことを前提とした場合の可用性(availability)を高めることに繋がる。
読みやすいコードを厳密に定義することは困難だが、代表的な考え方としてKISS原則とDRY原則がある。KISS原則とは「とにかく一つの関数では一つの作業をこなすように小さく作れ」という指針だ。一つのことをやるだけならコード行も少なくなり、読みやすくなる。それを端的に示した指標の一つが「50行ぐらい」だ。これは多くの作業画面1つに収まる程度の行数という意味合いであり、これを超えると全体を視認することが難しくなる。50を超えそうなら、それを複数の関数に分解できないか検討してみよう。
もう一つのDRY原則とは、同じコードや類似したコードが複数回出てくるようなら、それらを整理できないか考えようという指針だ。最もシンプルな例は「ある処理をN回繰り返す」なら、それはループで書けば良い。似ているけれども同一処理を繰り返すわけではない場合には、それをパターンとして整理できないか考えてみよう。例えば「リストの全要素に対して処理を行う」のは、リストから要素を取り出す部分以外は共通しているはずだ。このような「類似したコード」は抽象的な考え方で難しいが、紙の上で図表を書いてみるとわかりやすいことも多い(参考: 右脳と左脳のスイッチ)。
15.6. 演習¶
検討
下記内容をテキストファイル data.csv として用意し、実行イメージのように処理するコードを検討せよ。
id,score
e215780,50
e215781,80
>>> # 実行イメージ
>>> filename = 'data.csv'
>>> samples = read_data(filename)
>>> print(len(samples), samples)
2 {'e215780': 50, 'e215781': 80}
回答例
def read_data(filename: str) -> dict:
"""key,valueの2カラムを保存したCSVファイルを辞書型で読み込む
Arguments:
filename (str): 読み込むファイル名。keyはstr型、valueはint型想定。
Returns:
data (dict): filenameから読み込んだ辞書型オブジェクト。
"""
with open(filename, 'r') as f:
count = 0
data = {}
for line in f.readlines():
if count == 0:
count += 1
continue
items = line.split(',')
key = items[0]
value = int(items[1])
data[key] = value
count += 1
return data
filename = 'data.csv'
samples = read_data(filename)
print(len(samples), samples)