PEP8、PEP257で、人に見せても恥ずかしくないPythonコーディング！

## はじめに


こんにちは。早速ですが、皆さんが書いたソースコードは読みやすく書けていますか？

自分が書いたコードは、例えば複数人で共同開発するときや、インターネット上で公開するとき、納品するときなど、自分以外が目にする機会が多くあります。
そのようなときに書いたコードの体裁が整っていると、読み手だけでなく自分で自分のコードを見直すときも、誤解なくスピーディに理解できるようになります。

このようなときに、Pythonのコードの体裁を整えるのに用いられる規約が**PEP 8**、**PEP 257**です。

この記事ではPEP 8、PEP 257の内容を踏まえてこれに厳格に則るのではなく、**カジュアルに理解して最低限の見栄え**が達成できるような、代表的な決まりをいくつか紹介します。



## シバン(Shebang)、マジックコメント

```Python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
```

まずはコードの先頭によく書かれているこれです。1行目が**シバン(シェバン)** で2行目のものが**マジックコメント**と呼ばれるものです。

**シバン**は、「このファイルはこのプログラムで実行してください」というものを記述します。

これを記述しておくことで、このコード(仮にsample.pyというファイル名とします。)を実行したいとき、

```
$ python sample.py
```
ではなく

```
$ ./sample.py
```

のコマンドで実行できるようになります。

次に**マジックコメント**ですが、これはPEP8によるとPython3のソースコードであり且つUTF-8で書かれている場合**不要**とのことです。

マジックコメントは書かれているコードの文字エンコーディングを記述するもので、Python3ではデフォルトの文字コードがUTF-8であるため、記述するべきではないそうです。


## import文


import文の決まりは、大きく3つ挙げられます。

* まとめない

```Python
# OK
import os
import sys

# NG
import sys, os
```

* 親が同じならまとめても良い

```Python
from sklearn.model_selection import GridSearchCV, train_test_split
```

* 標準ライブラリ、サードパティ、ローカルで1行あける

```Python
import os
import sys

from sklearn.model_selection import GridSearchCV, train_test_split

from mypackage import sample
```


## Docstring


定義した関数やクラスに関する説明文です。これは記述するのに結構手間がかかりますが、あるのとないのとでは見栄えが段違いに変わります。

```Python
def my_func(x):
    """
    2乗の値を返す.

    Parameters
    ----------
    x : int
        対象の整数値

    Returns
    -------
    y : int
        入力の2乗の値
    """
    y = x ** 2
    return y
```

Docstringは**ダブルクォーテーション3つ**で囲みます。シングルクォーテーションはNGです。ダブルクォーテーションを打った行に続けて内容を記述しても構いません。

```Python
# これもOK
def my_func_hoge(x):
    """2乗の値を返す.

    Parameters
    ----------
    x : int
        対象の整数値

    Returns
    -------
    y : int
        入力の2乗の値
    """
    y = x ** 2
    return y


# せめてサマリだけでも書きましょう。
def my_func_fuga(x):
    """2乗の値を返す."""
    y = x ** 2
    return y
```
1行目には対象の関数やクラスのサマリを書きます。注意点として、**最後の文字は必ず半角ピリオド**にします。

サマリの次に1行空行を入れて引数を、引数の次は同様に1行の空行をはさみ返り値を列挙します。

これを書いておくとJupyter等で良いことがあるそうですが、ここでの説明は省略します。


## インデント

いわゆる字下げです。タブではなく**スペース4つ**にしましょう。ただし、tensorflowを使うときはインデントが深くなりがちであるので、スペース2つでも良いとされています。


* 関数などのカッコ内での改行

```Python
# 関数の引数か長くなってしまった場合は左カッコこ位置に合わせて改行
a = long_name_function(hikisu_ichi, hikisu_ni,
                       hikisu_san, hikisu_yon)

# インデントを下げて改行もOK
b = long_name_function(
    hikisu_ichi, hikisu_ni,
    hikisu_san, hikisu_yon)

# 途中からインデントを下げた改行はNG
c = long_name_function(hikisu_ichi, hikisu_ni,
    hikisu_san, hikisu_yon)

```

長い演算式中の改行

```Python
# 演算式の前で改行するか後で改行するか統一されていればOK
result_1 = (sushiki_ichi
            + sushiki_ni
            - (sushiki_san - susiki_yon)
            - susiki_go)

result_2 = (sushiki_ichi +
            sushiki_ni -
            (sushiki_san - susiki_yon) -
            susiki_go)
```


## 行間

トップレベル、つまりインデントなしの改行では原則2行、それ以外は1行以下の行間をあけましょう。

## 行中のスペース1文字あけるかどうか

* 左カッコの右側、右カッコの左側はあけない

```Python
# OK
hoge = {'fuga': [0]}

# NG
hoge = { 'fuga': [ 0 ] }
```

* カンマやコロンの直前にあけない

```Python
# OK
if a == b:
    c = {'d': 1}

# NG
if a == b :
    c = {'d' : 1}

# スライスに用いるコロンは例外
array[2:5]
```

* 代入演算子や、比較演算子、ブール演算子の両側にスペースをいれる

```Python
a = i + 1
b = c >= d
e = f not in g_list
h = j and k

# ただし、関数等におけるデフォルトパラメータの記述に使われる = の両側にはスペースをあけない
def hoge(piyo=None):
    pass

# 関数のキーワードを指定する際の引数の記述に使われる = の両側にもスペースをあけない
piyopiyo = hoge(piyo=1)
```

* 巨大な式の場合、演算子の優先度が最も高いものの両側にはなるべくスペースをあけないようにする

```Python
x = (b + (b**2 - 4*a*c) ** 0.5) / (-2*a)
```


## まとめ


いかがでしたか？今回はPEP 8やPEP 257の全てを網羅したわけではありませんが、ざっくりとどのようなところに注意して書けば良いか、という程度で理解していただければと思います。

もしあなたがこの記事を読んで、可読性や見栄えの良いコーディングを追求しようと思っていただけましたらとても嬉しいです。


## 参考

* pep8-ja 1.0 ドキュメント https://pep8-ja.readthedocs.io/ja/latest/
* PEP 257 -- Docstring Conventions | Python.org https://www.python.org/dev/peps/pep-0257/