Pythonをきれいに書きたい

# 1. はじめに
この記事では，Pythonのコーディングスタイルの一つであるPEP8についてまとめてみようと思います．
Pythonを書いているときに，空白や空行の入れ方に統一性がなくなってしまいコードが読みにくくなってしまうことがあるかとと思います．しかし，この記事に書いてあるPEP8などのコーディングスタイルに従って書くことで，統一感のある読みやすいコードが書けるようになるはずです．特に，複数人でコードを書くときにコーディングスタイルを共有することでそのありがたみがわかるはずです！
# 2. PEP 8とは?
Pythonの標準ライブラリで使用されているコーディングスタイルです．ピーイーピーエイト，ペップエイト，ペペイト（pepeightと繋げて読む Can Iをキャナイと読む感じ）などと読むようです．
今回は，[PEP 8 -- Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/)に記載されている内容の一部をまとめていきます．全部見ようとすると結構長いです...
## 愚かな一貫性？
[上で記載したページ](https://www.python.org/dev/peps/pep-0008/)では，イントロダクションの後に[**A Foolish Consistency is the Hobgoblin of Little Minds**](https://www.python.org/dev/peps/pep-0008/#a-foolish-consistency-is-the-hobgoblin-of-little-minds)と書かれています．これを直訳すると，「愚かな一貫性は，問題を引き起こす悪い生き物の小さな心だ」という意味になります．ここで言われているのは，**コーディングスタイルに固執しすぎるな**ということです．
コーディングスタイルを無視していい理由として以下が挙げられています．

1. コーディングスタイルに従うと読みにくくなる場合
1. 新しく記述する以外のコーディングスタイルに従っていないコードとの一貫性を保つ場合（コードをきれいにするチャンスかも）
1. コーディングスタイルを導入する前に書かれているコードで，コーディングスタイルに従うという目的以外でコードを修正する必要がない場合
1. コーディングスタイルに従うような書き方がサポートされていない古いバージョンを使用する必要がある場合

ここで述べられているように，コーディングスタイルに従う際には注意する必要があります．
## 1行の文字数はどうしたらいい？
1行の最大文字数は，**79文字**とされています．また，コメントやdocstring（クラスや関数の説明）は72文字とされています．これに従うことで，２つのファイルを横に並べてコードのレビューがしやすくなります．
## 長い行を分割するときは？
長い行を分割するには以下のやり方があります．

### バックスラッシュ（\）を使用する

```python
income = gross_wages + taxable_intere + \
(dividends - qualified_dividends) - \
ira_deduction - student_loean_interest
```

### 括弧で囲む

```python
income = (gross_wages + taxable_intere +
(dividends - qualified_dividends) -
ira_deduction - student_loean_interest)
```

ここでは，**括弧で囲む方法**を優先するべきであるとされています．しかし，括弧で囲むことができないwith-statementsなどではバックスラッシュを使用する方法で分割します．

しかし，ただ長い行を分けただけでは読みにくいままなので，スペースを入れて変数の始まりを揃えます．これは，関数を呼び出すときやリストを記述するときも同様です．

```python
income = (gross_wages + taxable_intere +
          (dividends - qualified_dividends) -
          ira_deduction - student_loean_interest)
```

演算子を縦に揃えて記述することで更に読みやすくなります．

```python
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loean_interest)
```

## 空行はどう入れる？
空行は，関連するものを分けるために**控えめに**入れます．
また，関数やクラスを記述する際の空行は以下のように入れます．

### クラス内の関数
クラス内の関数を記述する場合には関数同士の間に１行を空行を入れます．

```python
class ClassName:

    def __init__(self, name):
        self.name = name

    def class_function_name():
        print(self.name)
```

### トップレベルの関数・クラス
トップレベルの関数やクラスを記述する場合には，関数やクラスの間に２行空行を入れます．

```python
def function_name1():
    print('function1')


def function_name2():
    print('function2')


class ClassName:
    
    def __init__(self, name):
       self.name = name
    
    def class_function_name():
        print(self.name)
```

## 空白はどう入れる？
空白を入れる原則は以下になります．
- 空白は，１個のスペース（2個以上はだめ）
- 行末に空白は入れない（\で行を分割する際に構文エラーになったりする）

以下に詳細な空白の入れ方を挙げていきます．
### 括弧・カンマ・コロン周辺

```python
# 関数の引数を入れる括弧の前には入れない
spam(1)

# 辞書やリストも同様
dct['key'] = lst[0]

# 括弧の始まりの後，終わりの前は入れない
spam(ham[1], {eggs: 2})

# 要素が1つのみのタプルのカンマの後には入れない
foo = (0,)

# カンマやコロンの前には入れない，後には入れる
if x == 4: print x, y: x, y = y, x
```

### スライス
スライスのコロンは一番優先度が低い演算子として記述します．

```python
# コロンの前後に空白入れない場合
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]

# コロンの前後に空白を入れる場合
ham[lower+offset : upper+offset]
ham[lower + offset : upper + offset]

# パラメータが省略される場合は空白の省略
ham[lower:upper], ham[lower:upper:], ham[lower::step]
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
```

### 演算子周辺

```python
# 演算子の両側に空白
i = i + 1
submitted += 1

# 優先度の低い演算子の両側に空白
x = x*2 + 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
```

### 関数
キーワード引数やアノテーションのない関数パラメータのデフォルト値を示す場合にはイコールの前後には入れません．

```python
def complex(real, imag=0.0):
    return magic(r=real, i=image)
```


## 「'」と「"」はどっちを使う？
どちらかを推奨されてはいないが，どちらかに統一します．
しかし，文字列の中に「'」と「"」のどちらかが含まれている場合，エスケープシンボル（\）を避けるためなら無理して統一しなくても大丈夫です．
## Tabとスペースはどっちを使う？
スペースが推奨されています．
Pythonでは，Tabとスペースを混在させることは禁止されていため，新しいコードを追加するときはどちらが使われているか注意する必要があります．
## インポート文をどう書くか？
インポート文は必ずファイルの先頭に記述します．
インポート文を書くときには，コンマで繋げて１行で書かずに分けて記述します．

```python
# これは良くない
import sys, os

# こっちで書く
import os
import sys

```

同じモジュール内でのインポートの場合は１行で記述しても良です．しかし，ワイルドカード（*）の使用は避けるべきとされています．

```python
# これは良くない
from subprocess import *

# こっちで書く
from subprocess import Popen, PIPE
```
また，インポート文を記述する際には，以下の順番でグループ化します．

1. 標準ライブラリ
1. サードパーティのライブラリ
1. 自身で作成したもの

これらを空行１つで区切り，グループ化します．

```python
import os
import sys

import numpy as np
import pandas as pd

from my_tools import MyClass
```

# 3. VSCode上で確認する
VSCodeでPEP8に従っているかを確認するためにPEP8のラッパーであるflake8を利用します．
以下の手順を実行することで，コードを書いている途中にチェックが適応され，コードに波線が引かれます．

### pipでflake8をインストールする

```bash
pip install flake8
```

### VSCodeの設定を変更する
1. VSCodeを開いたときにある左下の歯車をクリック
1. 設定を選択
1. 検索ボックスにflake8と入力
1. 「Python > Lintling: Flake8 Enabled」の項目をクリックしてチェックを入れる

ここまでで従っていないコードに波線が引かれるようになります．

４でチェックを入れる際，「Python > Linting > Flake8 Category severity: ●」の項目をInfomationとしておくとコーティングスタイルに従っていないときの圧迫感がなくなる（ような気がする）のでおすすめです．

このように波線で確認することができるようになります．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1282063/c8dfd12b-6823-c2ab-1446-522b1b6e0576.png)

# 4. おわりに
最後まで読んでいただいてありがとうございました．
今回の記事を書いて，少しでも統一感があって読みやすいきれいなコードを書けるように心がけていこうと思います．また，**愚かな一貫性**についても心に止めておいて置こうと思っています．
折角なのでPEP8を知るきっかけになったUdemyの講座を紹介したいと思います．

https://www.udemy.com/course/python-beginner/

この講座はUdemyを使ったことがあれば知っている人も多いと思います．この講座ではPythonの基礎に加えて，コーディングスタイルやロギング，並列処理など幅広く学ぶことができるのでおすすめです！


# 5. 参考

https://www.python.org/dev/peps/pep-0008/

https://pep8-ja.readthedocs.io/ja/latest/

https://megatenpa.com/python/pep8-flake8/

http://trelab.info/visual-studio-code/python-vscode%E3%81%A7autopep8%E3%82%92%E9%81%A9%E7%94%A8%E3%81%99%E3%82%8B/