プログラマーとして、美しいコードを書くこと、つまり誰でも読みやすいコードを書くことは重要だと思います。
特に複数のプログラマーと共同開発する場合は、開発スピードの向上にも繋がります。
私がよく使うPythonは、元々とても読みやすい言語の1つですが、
コーディング規約に則って書くことで、さらに可読性を高めることができるでしょう。
今日はPythonの美しいコードを書くための、規約とコードチェックツールについてご紹介します💡
Pythonのコーディング規約: PEP 8
Pythonには、PEP 8と呼ばれるコーディング規約があります。
まず、PEPはPython Enhancement Proposal
の略で、Pythonに関連する様々な情報、プロセス、環境の新機能などを説明した文書群です。
PEP 8は、その8番目の文書であり、Pythonのコードスタイルについて記載されています。
PEP 8のルールで思いつくものをいくつか挙げてみます。
1. インデント
インデントは半角スペース4つで統一します。
基本的にタブは使用しませんが、既にタブでインデントされているコードとの一貫性を保ちたい場合はその限りではありません。
Python3では、インデントとしてタブとスペースを混合するとエラーになります。
また、長すぎる行を避けるために括弧内改行を行う場合は、引数を縦に揃えるか、または突き出しインデントを使用します。
# OK def example1(var): print(var) # OK def very_long_name_of_function(var_a, var_b, var_c): print(var_a) # OK 突き出しインデントはインデントのレベルを深くする def very_long_name_of_function( var_a, var_b, var_c): print(var_a) # NG print()とインデントが区別できないため def very_long_name_of_function( var_a, var_b, var_c): print(var_a)
2. 一行の長さ
全てのコード行は最大79文字にしましょう、と定められています。長い文は¥
を入れて改行しましょう。しかし1. インデントで言ったような、括弧内(関数の引数など)は'¥'不要で改行できます。
コメントは最大72文字です。
# OK with open('/path/to/some/file/you/want/to/read') as file_1, \ open('/path/to/some/file/being/written', 'w') as file_2: file_2.write(file_1.read())
3. import
import文は一番上にまとめ、各モジュール毎に書きます。しかし、1つのモジュールから複数のclassを呼び出すときは、一行で書いてもOKです。
# OK import os import sys # NG import os, sys # OK from subprocess import Popen, PIPE
4. 空行
各関数の処理内容によっては、どこで空行で区切るか難しいですが、通常の関数定義とclass 定義は空白2行、class内部の関数の定義は空白1行で区切ることが推奨されています。
class A(object): # contents of A def example1(var_1): print(var_1) def example2(var_2): print(var_2) class B(object): # contents of B
上記のように、誰がコーディングしても一貫性が保たれるようなルールが記述されています。
しかしいざ「ルールを守って書こうじゃないか!」と思っていても、チェックが漏れてしまうこともありますよね。
そんな時のために、コードを自動でチェックしてくれるツールが存在します。
コードチェックツールを使ってみる
様々なコードチェックツールがあります。
- pep8
- pyflakes
- flake8
- pylint
今回はその1つであるflake8を使ってみます。
flake8は、pep8とpyflakesの両方のチェックを同時に行えるラッパーなので、簡単にいうと検出されるエラーの範囲が広いです。
以下、各種pythonツールは下記の環境で動作確認しています。
- MacOS Catalina 10.15.2
- python 3.6.10
- pip 20.0.2
flake8の使い方
flake8のインストール
以下のコマンドで、インストールします。
$ pip install flake8
テスト用スクリプトの作成
テストのため、わざと規約に反する要素を含んだスクリプト(example.py
)を作成しました。
import os, sys a = "test" b = [1,2, 3 ] class example(): def print_moji(self, text): print( text ) def print_max(self,l): print(max(l)) if __name__ == "__main__": EX = example() EX.print_moji(a) EX.print_max(b)
どこに出しても恥ずかしいコードですね。
まずは、このスクリプトを通常通り実行します。
$ python example.py test 3
正常に動作します。
しかしコーディング規約に反する、余計なものだらけです。
読みにくいので、これではチームメイトに呆れられてしまいます。
flake8にチェックしてもらう
このスクリプトをflake8に投げてみます。
使うときは、$ flake8 <入力したいスクリプト>
と入力します。
$ flake8 example.py example.py:1:1: F401 'os' imported but unused example.py:1:1: F401 'sys' imported but unused example.py:1:10: E401 multiple imports on one line example.py:3:4: E222 multiple spaces after operator example.py:4:7: E231 missing whitespace after ',' example.py:4:12: E202 whitespace before ']' example.py:6:1: E302 expected 2 blank lines, found 1 example.py:9:15: E201 whitespace after '(' example.py:9:20: E202 whitespace before ')' example.py:10:5: E301 expected 1 blank line, found 0 example.py:10:23: E231 missing whitespace after ',' example.py:10:24: E741 ambiguous variable name 'l' example.py:13:1: E305 expected 2 blank lines after class or function definition, found 1 example.py:16:20: W291 trailing whitespace
ものすごく怒られました...。
flake8
の出力には、スクリプト名、何行目、何文字目、エラーコード、その詳細が記載されています。
上記の出力をエラーコード毎にまとめてみると、以下の通りです。
- E: コードスタイルに関するエラー
E201
: '('の後に余分なスペースがあります
E202
: ']'の前に余分なスペースがあります
E222
: スペースが重複しています
E231
:,
の後のスペースが抜けています
E302
: 2行の空白行が必要ですが、1行しかないです
E305
: class定義または関数定義の後は2行の空白行が必要ですが、1行しかないです
E401
: 複数のimportが一行で行われています
E741
: あいまいな変数名です
(小文字のエルl
は大文字のアイI
と間違えやすいので使わないでください)
- F: 論理的に矛盾したエラー
F401
:import
したモジュールが使用されていません
- W: 警告
W291
: 末尾に空白があります
修正する
指摘された内容にしたがって、コードを修正しました。
a = "test" b = [1, 2, 3] class example(): def print_moji(self, text): print(text) def print_max(self, var_list): print(max(var_list)) if __name__ == "__main__": EX = example() EX.print_moji(a) EX.print_max(b)
これで、flake8には怒られなくなりました。
$ flake8 example.py $
まとめ
規約に準ずるコードを書くことで、誰でも読めるようなコードに仕上がります。
ツールなどを駆使して、なるべくコーディング規約に準拠したコードを記述するように心がけましょう!
また、プロジェクトによってコーディングルールが異なる場合もありますので、周りの人と相談しながらコーディングできるとさらに良いですね✨