💪

AI系のコーディング基礎的お作法まとめ

に公開

「美しい」コード

一般に、「美しさ」には主観が多分に含まれる。芸術作品であるとか、俳優さん女優さんに対して使う場合は特にそうだろう。しかし、こと数学の証明だとかコーディングといったものに対して使用される場合、そうしたものたちは基本的に一定のルールに従っていることがほとんどだ。

「美しい」コードとはどんなもの?

美しいコードは読みやすい。
どのファイルにどの機能の関数があるか分かりやすく、保守性が高い。
そうであるから、1週間後・1ヶ月後の自分がみてもすぐその内容を思い出せるし、何より他人に見せても恥ずかしくない。

「美しい」コードを書くために

では、自分も他人も読みやすいコードはどんなルールに従っているのだろうか?
pythonを使用したAI系の研究とかデータサイエンス的な場合に満たすべき、基本的なポイントを整理しておく。

モジュール化

まずはコードを書く以前のディレクトリ構造の話だ。何も考えずにjupyter notebookを乱立させてはいないだろうか?jupyter notebookはnotebooksというディレクトリを作ってその中に数字の連番で置くのが良いだろう。また、作ったクラスや関数は機能単位で.pyファイルに整理し、srcディレクトリ内に置いておこう。
構成例は以下の記事参照。
https://zenn.dev/tsei/scraps/33cd0734ef73f7

使用データはdataディレクトリ内にまとめて置いておくことも多い。ただし、githubにpushして良いかどうかは事前によく考えよう。modelsの中に保存したモデルたちも同様。

jupyter notebookの落とし穴については以下も参照。
https://scicomp.aalto.fi/scicomp/jupyter-pitfalls/

main関数の使用

実行関数だと思っておけば良い。
src内に整理して置かれた(はずの)クラスや関数たちをimportし、実行する。しばしば、main.pyの中に書かれている。
main関数を定義して使用することのメリットはいくつかある。具体的な部分は先人の良い記事があるので、参照されたい。
https://www.lifewithpython.com/2021/01/python-main-function.html
個人的には、一番のメリットは抽象度の高い処理の流れをmain関数内で示せることだと思っている。load_data() -> preprocess_data() -> save_data()など。

パラメタを少しだけ変えてモデルの学習をしたいという場合、train.pyの中にargparseやclickつきのmain関数を準備しておいて、

python train.py --batch_size = 16

などとすることがある。clickを使ったtrain.pyの例は以下。

import click

@click.command()
@click.argument("batch_size")
@click.argument("hidden_size")
def main(batch_size, hidden_size):
    ...

if __name__ == "__main__":
    main()

typehint

基本的に、関数の引数とその出力の型を記しておくものである。pythonはCなどと違い、型宣言が必要ない言語であり、それが便利でもあるが型を全く考えないのは悪手だ、ということは覚えておこう。

def greet(name: str) -> str:
    return "Hello, " + name

以下の記事で先人も述べているが、まずは優先度の高いところから導入して徐々に広げていくのが良いだろう。たくさんのメリットがある。ちょっとした一手間を惜しまないように(自戒を込めて)。
https://note.com/shunk031/n/n02edafb543a6

docstring

平たく言えば定義した関数の説明文である。これがあるのとないのとで可読性が変わる。typehintと併用して存在すると良い。
VSCodeだと生成してくれる拡張機能があるので、意外と書くのは大変ではない。面倒でも、後々の自分や他者のために作っておこう。

def lambda_handler(event, context):
    """[summary]
    こういう説明文をdocstringという。
    Args:
        event ([type]): [description]
        context ([type]): [description]

    Returns:
        [type]: [description]
    """
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

https://qiita.com/flcn-x/items/393c6f1f1e1e5abec906
https://marketplace.visualstudio.com/items?itemName=njpwerner.autodocstring

なお、print(lambda_handler.__doc__)のようにすると、docstringの内容を出力して確認することができる。

コード構造そのものを美しく保つ

pythonはインデントが重要な言語。まずはインデントのやり方(tabなのかspaceなのか)を統一するところから始めよう。VSCode拡張機能にはインデントをカラーリングしてくれるものがあるので、入れて使ってみると良い。
https://marketplace.visualstudio.com/items?itemName=oderwat.indent-rainbow

コード整形ツールの使用も良いでしょう。ただ、初学者がいきなりそこまで手を伸ばさなくても良いかなと個人的には思います。以下によくまとまっているので、必要に応じて参照。
https://note.com/shunk031/n/n65c55ca011e3

githubでレビューしてもらおう

長々と述べてきたが、一番重要なのは先輩、先生、先人にレビューしてもらうことである。レビューしてもらいましょう(重要なことなので2回言いました)。何事も独りよがりはよくありません。

致命的なバグを後になって発見するより、レビューでボコボコにされる方が100倍マシです。

最後に

Beautiful is better than ugly. -- The Zen of Python by Tim Peters.

美しいコードを書こう!!

Discussion