Python コードのスタイルガイド
個人的に参考になった内容やよく使う(よく迷う)内容を備忘録的に引用します。Python のスタイルガイドは PEP(Python Enhancement Proposal) 8 で提案されています。
Style Guide for Python Code
Style Guide for Python Code(和訳)
インデント
インデント 1 段につき、スペース 4 個とする。
タブかスペースか
タブとスペースを、決して混在させてはならない。
Python で最も好まれるのは、スペースのみでインデントする方法である。
Python をコマンドラインから実行するときに、-t オプションをつけると、
ソースコード内にタブとスペースが不正に混在している旨を警告してくれる。
-tt オプションをつけると、警告ではなくエラーになる。
これらのオプションをつけることを強く推奨する!
一行の最大長さ
すべての行の最大長さは 79 文字とする。
長い行を折り返す際に望ましいのは、Python が暗に括弧内の行を継続する
ことを利用する方法である。必要であれば、式の周りを余分な括弧で囲むこ
とができるが、バックスラッシュを使う方が見栄えがいい場合もある。継続
する行を適切にインデントすることを忘れないように
空行
トップレベルの関数とクラス定義の間は、2 行空ける。
クラス内部でのメソッド定義の間は 1 行空けること。
関連する関数群の間に、余分な空行
を挟んでもよい(控えめに)。関連する1行プログラムのかたまりの間にあ
る空行は、省いてもよい。(たとえば、ダミーの実装の集まり)
関数内部でも、論理的な集まりを示すために、控えめに空行を使う。
import
- import は通常、別々の行に配置するべきである。
○ import sys
import os
× import sys, os
ただし、以下の記述はかまわない。
from subprocessimport Poepn, PIPE
- import は常に、ファイルの先頭のモジュールのコメントや docstring の
後、モジュールのグローバル定義の前に書く。
モジュールは以下に示すような順番でまとめておく。
1. 標準ライブラリの import
2. 関連するサードパーティの import
3. アプリケーションやライブラリ独自の import
各グループの間には空行を入れておくこと。
式や文の中のホワイトスペース
悩みの種
以下のような、余分な空白の使用を避ける。
- 括弧のすぐ内側
○ spam(ham[1], {eggs: 2})
× spam( ham[ 1 ], { eggs: 2 } )
- コンマ、セミコロン、コロンの直前
○ if x == 4: print x, y; x, y = y, x
× if x == 4 : print x , y ; x , y = y , x
- 関数呼び出しで、引数リストが始まる開き括弧の直前
○ spam(1)
× spam (1)
- インデックスやスライスが始まる開き括弧の直前
○ dict['key'] = list[index]
× dict ['key'] = list [index]
- 代入演算子(または他の演算子)のまわりに、1文字以上のスペースを配
置して、別の式と列揃えをすること。
○
x = 1
y = 2
long_variable = 3
×
x = 1
y = 2
long_variable = 3
その他の推奨案
- バイナリ演算子の両側は、常にスペース1個で挟む。代入演算子(=)、
拡張代入演算子 (+=、 -= など)、比較演算子(==, <, >, !=, <>, <=,
>=, in, not in, is, is not)、ブール演算子(and, or, not)に適用す
る。
- 算術演算子の前後にスペースを置く。
○
i = i + 1
submitted += 1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
×
i=i+1
submitted +=1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
- '=' 記号を、キーワード引数やデフォルトのパラメータ値として使う場合、
'='記号の両側にスペースを配置しないこと。
○
def complex(real, imag=0.0):
return magic(r=real, i=imag)
×
def complex(real, imag = 0.0):
return magic(r = real, i = imag)
- 複文(1行に書かれた複数の文)は書かないことが推奨されている。
○
if foo == 'blah':
do_blah_thing()
do_one()
do_two()
do_three()
△
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()
- if、for、while ブロックの中身が小さいときには 1 行で書いてもよい。
ただし、複文の場合には 1 行で書いてはならない。
△
if foo == 'blah': do_blah_thing()
for x in lst: total += x
while t < 10: t = delay()
×
if foo == 'blah': do_blah_thing()
else: do_non_blah_thing()
try: something()
finally: cleanup()
do_one(); do_two(); do_three(long, argument,
list, like, this)
if foo == 'blah': one(); two(); three()
バージョンの記録
ソースファイル内にRCSやCVSの情報を持たせる必要がある場合には、以下の
ようにする。
__version__ = "$Revision: 1.20 $"
# $Source: /cvsroot/python/python/nondist/peps/pep-0008.txt,v
これらの行はモジュールのdocstringより後ろ、その他のソースコードより
前に、空行で分離して書いておく。
命名規則
パッケージ名とモジュール名
モジュール名には、アンダースコアを含まない短い lowercase を使う。
クラス名
ほぼ例外なく、クラス名にはCapWords方式を使う。内部使用のクラス名に
は、先頭にアンダースコアを追加する。
例外名
例外はクラスなので、クラスの命名規則を適用する。ただし、「Error」
を接辞する(もしその例外が実際にエラーであるなら)。
グローバル変数名
(これらの変数は1つのモジュール内でのみ使われるものだと、願いま
しょう)関数とほぼ同じ規則を適用する。
関数名
関数名は lowercase 方式で命名し、可読性のためにアンダースコアで単
語を区切ってもよい。
関数やメソッドの引数
インスタンスメソッドの第 1 引数には、常に「self」を使う。
クラスメソッドの第 1 引数には、常に「cls」を使う。
メソッド名とインスタンス変数
関数の場合と同じルールを使う。lowercase 方式で命名し、可読性を上げ
るためにアンダースコアで単語を区切る。
非公開なメソッドとインスタンス変数にのみ、先頭にアンダースコアを1
つ使って命名する。
サブクラスとの名前の衝突を避けるには、先頭にアンダースコアを2つ付
けることで、Python の名前修飾ルールが行われる。
Python は先頭にアンダースコアが2つあるような名前があると、クラス名
で修飾する。Foo クラスに __a という属性があると、Foo.__a という形
式でアクセスすることはできない(Foo._Foo__a でアクセスできるけれど)。
一般に、先頭に2つのアンダースコアがついた名前は、サブクラス化され
るクラスにおいて名前が衝突するのを避けるために仕様するべきである。
継承のための設計
クラスのメソッドやインスタンス変数(つまり「属性」)を公開すること
の是非を、常に考慮する。どちらがいいか分からないときには、非公開に
する。公開属性を非公開にするよりも、非公開属性を公開にするほうが容
易である。
プログラミングにおける推奨案
- クラスを使った例外は、文字列を使った例外よりも望ましい。
- string モジュールではなく、文字列メソッドを使う。
文字列メソッドは常に高速であり、Unicode 文字列と同じ API を共有し
ている。Python 2.0 以前のバージョンとの後方互換が必要な場合のみ、
文字列メソッドを使う。
- 接頭辞や接尾辞を調べるときに、文字列のスライスを使うのを避けること。
代わりに startswith() と endswith() を使う。こちらのほうがきれいで、
エラーが起こりにくい。以下に例を示す。
○ if foo.startswith('bar'):
× if foo[:3] == 'bar':
- オブジェクト型の比較には、常に isinstance() を使い、型を直接比較しないこと。
○ if isinstance(obj, int):
× if type(obj) is type(1):
- シーケンス(文字列、リスト、タプル)では、空のシーケンスは偽である
ことを利用する。
○ if not seq:
if seq:
× if len(seq):
if not len(seq):
- ブール値を、== を使って True や False と比較しない。
○ if greeting:
× if greeting == True: