[python] pep8規約まとめ
Pythonのコードスタイルガイドpep8のまとめ。
- コードのレイアウト
- インデント
- 突き出しインデントを使う場合ははじめの行には引数を付けずに次の行以降をインデントし継続行だとはっきりわかるようにしましょう
- 波括弧/ブラケット/括弧 を閉じる時は、「リストの最後の要素が置かれた行の、はじめのホワイトスペースでない文字の直下」に閉じる記号を置いても構いません。
- 閉じる記号を「継続された行のはじめの文字」に合わせて置いても構いません。
- タブか、スペースか?スペースが好ましいインデントの方法です。
- 1行の長さ。すべての行の長さを、最大79文字までに制限しましょう。
- 長い行を折り返す好ましい方法は、Pythonが括弧やブラケット、波括弧の中では暗黙のうちに行を継続させることを利用することです。
- 段落の中にある式は、常に2項演算子や関係演算子の後で改行しますが、構造化された式は常に2項演算子の前で改行します
- トップレベルの関数やクラスは、2行ずつ空けて定義するようにしてください。
- クラス内部では、1行ずつ空けてメソッドを定義してください。
- 関数の中では、ロジックの境目を示すために、空行を控えめに使うようにします。
- Python のコアディストリビューションに含まれるコードは常に UTF-8 (Python 2 では ASCII) を使用すべきです。
- import文は、通常は行を分けるべきです:
- 1つのサブモジュールからインポートする場合は、行を分けなくてよい
- import文 は常にファイルの先頭、つまり モジュールコメントや docstring の直後、そしてモジュールのグローバル変数や定数定義の前に置くようにします。
- import文 は次の順番でグループ化すべきです:
- 絶対import を推奨します
- クラスを含んだモジュールからクラスをimportする場合
- ワイルドカードを使った import (from
import *) は避けるべきです。 - モジュールレベルの “二重アンダースコア変数” (変数名の前後にアンダースコアが2つ付いている変数) は、モジュールに関する docstring の後、そして from future 以外の あらゆるimport文の前に置くべきです。
- 文字列に含まれる引用符
- 式や文中の空白文字
- 括弧やブラケット、波括弧 のはじめの直後と、終わりの直前に、余計な空白文字を使うのはやめましょう
- 末尾のカンマと、その後に続く閉じカッコの間に、余計な空白文字を使うのはやめましょう
- カンマやセミコロン、コロンの直前に、余計な空白文字を使うのはやめましょう
- スライスではコロンは二項演算子のように振る舞います。よって、(コロンは優先度が最も低い演算子として扱われるので)両側に同じ数(訳注: 無しでも可だと思われる)のスペースを置くべきです。
- 関数呼び出しの引数リストをはじめる開き括弧の直前に、余計な空白文字を使うのはやめましょう
- インデックスやスライスの開き括弧の直前に、余計な空白文字を使うのはやめましょう
- 代入(や他の)演算子を揃えるために、演算子の周囲に1つ以上のスペースを入れることはやめましょう
- 行末に余計な空白文字を残さないようにしましょう
- 次の2項演算子は、両側に常にひとつだけスペースを入れましょう
- 優先順位が違う演算子を扱う場合、優先順位が一番低い演算子の両側にスペースを入れることを考えてみましょう
- 関数アノテーションは、 コロンに関する通常のルール(訳注:コロンの前には余計なスペースを入れない)を守るようにしつつ、 -> 演算子がある場合、その両側には常にスペースを入れるようにしましょう
- アノテーションされていない 関数の引数におけるキーワード引数や、デフォルトパラメータを示す = の両側にスペースを入れてはいけません
- しかし、デフォルト値をもった引数アノテーションと組み合わせる場合、 = の前後にはスペースを入れるようにしてください
- 複合文 (一行に複数の文を入れること) は一般的に推奨されません。
- if/for/while と 短い文を同じ行に置くことがOKな場合もありますが、複合文を置くのはやめてください。また、複合文でできた長い行を折り返すのもやめましょう
- 末尾にカンマを付けるべき場合
- コメント
- コードと矛盾するコメントは、コメントしないことよりタチが悪いです。コードを変更した時は、コメントを最新にすることをいつも優先させてください
- コメントは複数の完全な文で書くべきです。はじめの単語はそれが小文字で始まる識別子でない限り、大文字にすべきです(間違ってもその識別子の大文字小文字を変更しないでね!)。
- コメントが2つ以上の文からなる場合、文の終わりのピリオドの後は、二つスペースを入れるべきです。ただし、最後の文を除きます。
- 英語を話さない国出身の Python プログラマの方々へ:あなたのコードが、自分の言葉を話さない人に 120% 読まれないと確信していなければ、コメントを英語で書くようにお願いします。
- ブロックコメント内の段落は、# だけを含んだ1行で区切るようにします。
- 自明なことを述べている場合、インラインコメントは不要ですし、邪魔です。次のようなことはしないでください:
- すべての公開されているモジュールや関数、クラス、メソッドの docstring を書いてください
- PEP 257 は良い docstring の規約です。もっとも重要なのは、複数行の docstring は “”” だけからなる行で閉じることです
- docstring が1行で終わる場合は、同じ行を “”” で閉じるようにしてください
- 命名規約
- 公開されている API の一部としてユーザーに見える名前は、実装よりも使い方を反映した名前にすべきです
- 命名のやり方には多くのバリエーションがあります。よく知られたやり方として、次のものが挙げられます
- アンダースコアを名前の前後に付ける特別なやり方が知られています
- 単一の文字 ‘l’ (小文字のエル)、’O’ (大文字のオー)、’I’(大文字のアイ) を決して変数に使わないでください
- 標準ライブラリで使われる識別子は、PEP 3131 の policy section にあるとおり、 ASCII と互換性がなければなりません
- モジュールの名前は、全て小文字の短い名前にすべきです
- クラスの名前には通常 CapWords 方式を使うべきです
- PEP 484 で導入された型変数の名前には、通常 CapWords 方式を使うべきです
- 例外はクラスであるべきです
- 関数の名前は小文字のみにすべきです
- 関数の名前は読みやすくするために、必要に応じて単語をアンダースコアで区切るべきです
- 変数の名前についても、関数と同じ規約に従います
- インスタンスメソッドのはじめの引数の名前は常に self を使ってください
- クラスメソッドのはじめの引数の名前は常に cls を使ってください
- 関数の引数名が予約語と衝突していた場合、アンダースコアを引数名の後ろに追加するのが一般的には望ましいです
- メソッド名とインスタンス変数は関数の命名規約を使ってください
- 全ての定数は大文字で書き単語をアンダースコアで区切ります
- クラスのメソッドやインスタンス変数(まとめて “属性” といいます)を公開するかどうかをいつも決めるようにしましょう
- Pythonicなガイドライン
- イントロスペクションがうまく機能するようにするためモジュールは公開しているAPIを all 属性を使ってすべて宣言すべきです
- importされた名前は常に実装の詳細を表現していると見なすべきです
- プログラミングに関する推奨事項
- たとえば a += b や a = a + b のように、データを直接置き換える CPython の効率的な実装に依存しないでください
- ライブラリの中でパフォーマンスに敏感な部分には”.join() を代わりに使うべきです
- Noneのようなシングルトンと比較をする場合は、常にisかis notを使うべきです
- if x is not None と書いているつもりで、 if x と書いている場合は注意してください
- not…is …ではなくis not演算子を使いましょう
- 拡張比較(rich comparion)を使って並び替えを実装する場合、特定の比較を実行するだけの他のコードに依存するよりはむしろ、全ての演算を実装するのがベストです
- ラムダ式を直接識別子に結びつける代入文を書くのではなくて常にdef文を使いましょう
- BaseExceptionではなくてExceptionから例外を派生させるようにしましょう
- 例外をキャッチする時は可能なときはいつでも例外を指定しない生のexceptではなく特定の例外を指定するようにしましょう
- 生のexceptを使う場合を次の二つに限ること
- リソースがコードの特定の部分だけで使われる場合使った後すぐ信頼できるやり方で後始末ができるようにwith文を使いましょう
- 関数の中の全てのreturn文は式を返すか全く何も返さないかのどちらかにすべきです
- 文字列に特定のプレフィックスやサフィックスがついているかをチェックするには文字列のスライシングではなく “.startswith() と “.endswith() を使いましょう
- オブジェクトの型の比較は型を直接比較するかわりに常にisinstance()を使うようにすべきです
- シーケンス(文字列,リスト,タプル)については空のシーケンスがFalseであることを利用しましょう
- 行末の空白文字に依存した文字列リテラルを書かないでください
- ブール型の値とTrueやFalseを比較するのに==を使うのはやめましょう
- finallyの外に脱出する制御構文を使うのは推奨されません
- 関数アノテーションをPEP484とは違うスタイルで使いたいコードについては次のようなコメントを付けておくことを推奨します
コードのレイアウト
インデント
1レベルインデントするごとに、スペースを4つ使いましょう。
行を継続する場合は、折り返された要素を縦に揃えるようにすべきです。
正しい
foo = long_function_name(var_one, var_two,
var_three, var_four)
間違い
foo = long_function_name(var_one, var_two,
var_three, var_four)
突き出しインデントを使う場合ははじめの行には引数を付けずに次の行以降をインデントし継続行だとはっきりわかるようにしましょう
突き出しインデント は、はじめの行以外の全ての行をインデントするDTPのやり方です。Python の文脈では、括弧で囲む文の開き括弧を行の終わりに置いて、残りの行を閉じ括弧までインデントするスタイルのことを言います。
# 突き出しインデントはインデントのレベルを深くする
foo = long_function_name(
var_one, var_two,
var_three, var_four)
# 突き出しインデントはインデントのレベルを深くする
foo = long_function_name(
var_one, var_two,
var_three, var_four)
波括弧/ブラケット/括弧 を閉じる時は、「リストの最後の要素が置かれた行の、はじめのホワイトスペースでない文字の直下」に閉じる記号を置いても構いません。
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
閉じる記号を「継続された行のはじめの文字」に合わせて置いても構いません。
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
タブか、スペースか?スペースが好ましいインデントの方法です。
- Python 3 では、インデントにタブとスペースを混ぜることを禁止しています。
- インデントにタブとスペースを混ぜた Python 2 のコードは、スペースだけを使うように変換すべきです。
- Python 2 のコマンドラインインタプリタを -t オプションを付けて呼び出すと、タブとスペースをインデントに混ぜたコードに対して警告を出します。-tt を付けるとエラーになります。これらのオプションの使用を強く推奨します!
1行の長さ。すべての行の長さを、最大79文字までに制限しましょう。
- エディタのウィンドウの幅を制限すると、複数のファイルを並べて開くことができ、二つのバージョンを隣り合ったカラムに表示するコードレビューツールを使うときにもうまくいきます。
- ほとんどのツールのデフォルトの折り返し動作は、コードの見た目の構造を壊し、理解するのを難しくします。79文字という制限は、ウィンドウの幅を80に制限し、行を折り返すときにツールが行末にマーカーを置いたとしても、エディタに折り返す動作をさせない目的で選ばれています。
- Python の標準ライブラリは保守的なので、1行の文字数は79文字に制限することが必須です(docstring やコメントは72文字)。
長い行を折り返す好ましい方法は、Pythonが括弧やブラケット、波括弧の中では暗黙のうちに行を継続させることを利用することです。
- 長い行は文を括弧で囲むことで、複数行に分割できます。行を継続させるには、バックスラッシュよりもこれらを使用すべきです。
段落の中にある式は、常に2項演算子や関係演算子の後で改行しますが、構造化された式は常に2項演算子の前で改行します
この数学の伝統に従うと、通常はもっと読みやすいコードになります:
# 正しい:
# 演算子とオペランドを一致させやすい
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
# 間違い:
# 演算子がオペランドと離れてしまっている
income = (gross_wages +
taxable_interest +
(dividends - qualified_dividends) -
ira_deduction -
student_loan_interest)
トップレベルの関数やクラスは、2行ずつ空けて定義するようにしてください。
クラス内部では、1行ずつ空けてメソッドを定義してください。
関数の中では、ロジックの境目を示すために、空行を控えめに使うようにします。
Python のコアディストリビューションに含まれるコードは常に UTF-8 (Python 2 では ASCII) を使用すべきです。
- ASCII (Python 2) や UTF-8 (Python 3) を使用しているファイルにはエンコーディング宣言を入れるべきではありません。
import文は、通常は行を分けるべきです:
# 正しい:
import os
import sys
# 悪い:
import sys, os
1つのサブモジュールからインポートする場合は、行を分けなくてよい
# 正しい:
from subprocess import Popen, PIPE
import文 は常にファイルの先頭、つまり モジュールコメントや docstring の直後、そしてモジュールのグローバル変数や定数定義の前に置くようにします。
import文 は次の順番でグループ化すべきです:
- 標準ライブラリ
- サードパーティに関連するもの
- ローカルな アプリケーション/ライブラリ に特有のもの
上のグループそれぞれの間には、1行空白を置くべきです。
絶対import を推奨します
なぜなら、絶対import の方が通常は読みやすく、importシステムが正しく設定されなかった(たとえばパッケージ内部のディレクトリが sys.path で終わっていた) 場合でも、より良い振る舞いをする(または少なくともより良いエラーメッセージを出す)からです:
import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example
クラスを含んだモジュールからクラスをimportする場合
次のようにしても通常はOKです:
from myclass import MyClass
from foo.bar.yourclass import YourClass
このやり方で名前の衝突が起きたら、次のように明示的にimportします:
import myclass
import foo.bar.yourclass
ワイルドカードを使った import (from import *) は避けるべきです。
- なぜなら、どの名前が名前空間に存在しているかをわかりにくくし、コードの読み手や多くのツールを混乱させるからです。
- ワイルドカードを使った import を正当化できるユースケースがひとつあります。内部インターフェイスを公開APIとして再公開する場合 (たとえば、Pure Python の実装をオプションの高速化モジュールの内容で上書きし、どの定義が上書きされるかがあらかじめわからない場合) です。
モジュールレベルの “二重アンダースコア変数” (変数名の前後にアンダースコアが2つ付いている変数) は、モジュールに関する docstring の後、そして from future 以外の あらゆるimport文の前に置くべきです。
- Python はfuture importを、docstring 以外のあらゆるコードの前に置くように強制します:
"""This is the example module.
This module does stuff.
"""
from __future__ import barry_as_FLUFL
__all__ = ['a', 'b', 'c']
__version__ = '0.1'
__author__ = 'Cardinal Biggles'
import os
import sys
文字列に含まれる引用符
三重引用符 で文字列を囲むときは、PEP 257 での docstring に関するルールと一貫させるため、常に二重引用符 “”” を使うようにします。
式や文中の空白文字
括弧やブラケット、波括弧 のはじめの直後と、終わりの直前に、余計な空白文字を使うのはやめましょう
# 正しい:
spam(ham[1], {eggs: 2})
# 間違い:
spam( ham[ 1 ], { eggs: 2 } )
末尾のカンマと、その後に続く閉じカッコの間に、余計な空白文字を使うのはやめましょう
# 正しい:
foo = (0,)
# 間違い:
bar = (0, )
カンマやセミコロン、コロンの直前に、余計な空白文字を使うのはやめましょう
# 正しい:
if x == 4: print x, y; x, y = y, x
# 間違い:
if x == 4 : print x , y ; x , y = y , x
スライスではコロンは二項演算子のように振る舞います。よって、(コロンは優先度が最も低い演算子として扱われるので)両側に同じ数(訳注: 無しでも可だと思われる)のスペースを置くべきです。
# 正しい:
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
ham[lower:upper], ham[lower:upper:], ham[lower::step]
ham[lower+offset : upper+offset]
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
ham[lower + offset : upper + offset]
# 間違い:
ham[lower + offset:upper + offset]
ham[1: 9], ham[1 :9], ham[1:9 :3]
ham[lower : : upper]
ham[ : upper]
関数呼び出しの引数リストをはじめる開き括弧の直前に、余計な空白文字を使うのはやめましょう
# 正しい:
spam(1)
# 間違い:
spam (1)
インデックスやスライスの開き括弧の直前に、余計な空白文字を使うのはやめましょう
# 正しい:
dct['key'] = lst[index]
# 間違い:
dct ['key'] = lst [index]
代入(や他の)演算子を揃えるために、演算子の周囲に1つ以上のスペースを入れることはやめましょう
# 正しい:
x = 1
y = 2
long_variable = 3
# 間違い:
x = 1
y = 2
long_variable = 3
行末に余計な空白文字を残さないようにしましょう
- 通常それは目に見えないため、混乱のもとになるかもしれません。たとえば、バックスラッシュの後にスペースをひとつ入れて改行してしまうと、行を継続すると見なされません。
- エディタによっては行末の余計な空白文字を保存しないものもありますし、多くのプロジェクト (CPythonもそうです) ではコミット前のフックでそれを拒否するように設定しています。
次の2項演算子は、両側に常にひとつだけスペースを入れましょう
- 代入演算子 (=)
- 拡張代入演算子 (+=, -= など.)
- 比較演算子 (==, <, >, !=, <>, <=, >=, in, not in, is, is not)
- ブール演算子 (and, or, not)
優先順位が違う演算子を扱う場合、優先順位が一番低い演算子の両側にスペースを入れることを考えてみましょう
- 入れるかどうかはあなたの判断にお任せしますが、二つ以上のスペースを絶対に使わないでください
- そして、2項演算子の両側には、常に同じ数の空白文字を入れてください
# 正しい:
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 munge(input: AnyStr): ...
def munge() -> PosInt: ...
# 間違い:
def munge(input:AnyStr): ...
def munge()->PosInt: ...
アノテーションされていない 関数の引数におけるキーワード引数や、デフォルトパラメータを示す = の両側にスペースを入れてはいけません
# 正しい:
def complex(real, imag=0.0):
return magic(r=real, i=imag)
# 間違い:
def complex(real, imag = 0.0):
return magic(r = real, i = imag)
しかし、デフォルト値をもった引数アノテーションと組み合わせる場合、 = の前後にはスペースを入れるようにしてください
# 正しい:
def munge(sep: AnyStr = None): ...
def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...
# 間違い:
def munge(input: AnyStr=None): ...
def munge(input: AnyStr, limit = 1000): ...
複合文 (一行に複数の文を入れること) は一般的に推奨されません。
# 正しい:
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 と 短い文を同じ行に置くことがOKな場合もありますが、複合文を置くのはやめてください。また、複合文でできた長い行を折り返すのもやめましょう
やらない方が良い:
# 間違い:
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()
末尾にカンマを付けるべき場合
要素数がひとつのタプルを作るときは、(技術的には冗長ですが) 括弧で囲むことを推奨します
# 正しい:
FILES = ('setup.cfg',)
# 間違い:
FILES = 'setup.cfg',
末尾のカンマは冗長ですが、便利な場合もあります
- たとえば値や引数、もしくはimportされた値のリストが繰り返し展開されることが期待される場合や、バージョン管理システムを使っている場合です。
- それぞれの値(など)を一行にひとつずつ置き、末尾にカンマをひとつ追加し、その次の行を 閉じ括弧/角括弧/中括弧 で閉じるというのがひとつのパターンです。
- しかし、区切りの終わりを示す目的で、同じ行の末尾にカンマを付けることは意味がありません
# 正しい:
FILES = [
'setup.cfg',
'tox.ini',
]
initialize(FILES,
error=True,
)
# 間違い:
FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)
コメント
コードと矛盾するコメントは、コメントしないことよりタチが悪いです。コードを変更した時は、コメントを最新にすることをいつも優先させてください
コメントは複数の完全な文で書くべきです。はじめの単語はそれが小文字で始まる識別子でない限り、大文字にすべきです(間違ってもその識別子の大文字小文字を変更しないでね!)。
コメントが2つ以上の文からなる場合、文の終わりのピリオドの後は、二つスペースを入れるべきです。ただし、最後の文を除きます。
英語を話さない国出身の Python プログラマの方々へ:あなたのコードが、自分の言葉を話さない人に 120% 読まれないと確信していなければ、コメントを英語で書くようにお願いします。
ブロックコメント内の段落は、# だけを含んだ1行で区切るようにします。
自明なことを述べている場合、インラインコメントは不要ですし、邪魔です。次のようなことはしないでください:
x = x + 1 # xを1増やす
しかし次のように、役に立つ場合もあります:
x = x + 1 # 境目を補う
すべての公開されているモジュールや関数、クラス、メソッドの docstring を書いてください
- docstring は公開されていないメソッドには不要ですが、そのメソッドが何をしているのかは説明すべきです。
- このコメントは def の行のあとに置くべきです。
PEP 257 は良い docstring の規約です。もっとも重要なのは、複数行の docstring は “”” だけからなる行で閉じることです
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""
docstring が1行で終わる場合は、同じ行を “”” で閉じるようにしてください
命名規約
公開されている API の一部としてユーザーに見える名前は、実装よりも使い方を反映した名前にすべきです
命名のやり方には多くのバリエーションがあります。よく知られたやり方として、次のものが挙げられます
- b (小文字1文字)
- B (大文字1文字)
- lowercase
- lower_case_with_underscores
- UPPERCASE
- UPPER_CASE_WITH_UNDERSCORES
- CapitalizedWords (CapWords, または CamelCase - 文字がデコボコに見えることからこう呼ばれます)。StudlyCaps という呼び名でも知られています。
- mixedCase (はじめの文字が小文字である点が、CapitalizedWords と違います!)
- Capitalized_Words_With_Underscores (醜い!)
アンダースコアを名前の前後に付ける特別なやり方が知られています
- これらに大文字小文字に関する規約を組み合わせるのが一般的です
- _single_leading_underscore: “内部でだけ使う” ことを示します。 たとえば from M import * は、アンダースコアで始まる名前のオブジェクトをimportしません。
single_trailingunderscore: Python のキーワードと衝突するのを避けるために使われる規約です。例を以下に挙げます:
tkinter.Toplevel(master, class_='ClassName')
__double_leading_underscore: クラスの属性に名前を付けるときに、名前のマングリング機構を呼び出します (クラス Foobar の boo という名前は _FooBarboo になります。以下も参照してください)
double_leading_and_trailing_underscore: ユーザーが制御する名前空間に存在する “マジック”オブジェクト または “マジック”属性です。 たとえば init, import, file が挙げられます。この手の名前を再発明するのはやめましょう。ドキュメントに書かれているものだけを使ってください。
単一の文字 ‘l’ (小文字のエル)、’O’ (大文字のオー)、’I’(大文字のアイ) を決して変数に使わないでください
- フォントによっては、これらの文字は数字の1や0と区別が付かない場合があります。
- ‘l’(小文字のエル) を使いたくなったら、’L’ を代わりに使いましょう。
標準ライブラリで使われる識別子は、PEP 3131 の policy section にあるとおり、 ASCII と互換性がなければなりません
モジュールの名前は、全て小文字の短い名前にすべきです
- 読みやすくなるなら、アンダースコアをモジュール名に使っても構いません。
- Python のパッケージ名は、全て小文字の短い名前を使うべきですが、アンダースコアを使うのは推奨されません。
クラスの名前には通常 CapWords 方式を使うべきです
PEP 484 で導入された型変数の名前には、通常 CapWords 方式を使うべきです
- また、 T や AnyStr や Num のような短い名前が好ましいです。
- 共変や反変の振る舞いをする変数を宣言するために _co や _contra のような名前を変数の末尾に付け加えることを推奨します
from typing import TypeVar
VT_co = TypeVar('VT_co', covariant=True)
KT_contra = TypeVar('KT_contra', contravariant=True)
例外はクラスであるべきです
- (その例外が実際にエラーである場合は) 例外の名前の最後に “Error” をつけるべきです。
関数の名前は小文字のみにすべきです
関数の名前は読みやすくするために、必要に応じて単語をアンダースコアで区切るべきです
変数の名前についても、関数と同じ規約に従います
インスタンスメソッドのはじめの引数の名前は常に self を使ってください
クラスメソッドのはじめの引数の名前は常に cls を使ってください
関数の引数名が予約語と衝突していた場合、アンダースコアを引数名の後ろに追加するのが一般的には望ましいです
- 衝突した名前を変更しようとして、略語を使ったりスペルミスをするよりマシです。
- よって、 class_ は clss より好ましいです
メソッド名とインスタンス変数は関数の命名規約を使ってください
- 名前は小文字のみにして、読みやすくするために必要に応じて単語をアンダースコアで区切ります。
- 公開されていないメソッドやインスタンス変数にだけ、アンダースコアを先頭に付けてください。
- サブクラスと名前が衝突した場合は、Python のマングリング機構を呼び出すためにアンダースコアを先頭に二つ付けてください。
全ての定数は大文字で書き単語をアンダースコアで区切ります
クラスのメソッドやインスタンス変数(まとめて “属性” といいます)を公開するかどうかをいつも決めるようにしましょう
- よくわからないなら、公開しないでおきます。
- なぜなら、公開されている属性を非公開にすることよりも、非公開の属性を公開することの方がずっと簡単だからです。
Pythonicなガイドライン
- 公開されている(public)属性の先頭にはアンダースコアを付けない
- もしあなたが公開している属性の名前が予約語と衝突する場合は、属性の名前の直後にアンダースコアを追加します。省略語を使ったり、スペルミスをするよりはマシです。 (しかし、このルールに関わらず、’cls’ という名前はクラスを示す変数や引数、特にクラスメソッドのはじめの引数として望ましいものです)
- 公開する属性をシンプルにするには、複雑なアクセサやミューテータ(訳注:内部状態を変更するメソッド) を公開せず、属性の名前だけを公開するのがベストです。そういった属性に関数的な振る舞いが必要になった場合でも、Python はそういった拡張を将来簡単に行える手段を提供していることを覚えておきましょう。この場合は、関数呼び出しの実装をシンプルなデータアクセスの文法で隠すために、プロパティを使います。
- サブクラス化して使うクラスがあるとします。サブクラスで使って欲しくない属性があった場合、その名前の最後ではなく、先頭にアンダースコアを二つ付けることを検討してみましょう。これによって Python のマングリングアルゴリズムが呼び出され、その属性にはクラス名が付加されます。これはサブクラスにうっかり同名の属性が入ってしまうことによる属性の衝突を避けるのに役立ちます。
イントロスペクションがうまく機能するようにするためモジュールは公開しているAPIを all 属性を使ってすべて宣言すべきです
- all 属性を空にすると、そのモジュールには公開しているAPIはないということになります。
- all 属性を適切に設定したとしても、内部インターフェイス (パッケージ、モジュール、クラス、関数、属性、その他の名前) は名前の前にアンダースコアをひとつ付けるべきです。
importされた名前は常に実装の詳細を表現していると見なすべきです
プログラミングに関する推奨事項
たとえば a += b や a = a + b のように、データを直接置き換える CPython の効率的な実装に依存しないでください
- この最適化は CPython の場合でも弱い(いくつかの型でしか機能しません)ですし、リファレンスカウントが入っていないPython実装には存在しません
ライブラリの中でパフォーマンスに敏感な部分には”.join() を代わりに使うべきです
- このやり方であれば、様々なPython実装で、文字列の連結が線形時間で終わることを保証してくれます
Noneのようなシングルトンと比較をする場合は、常にisかis notを使うべきです
- 絶対に等値演算子を使わないでください
if x is not None と書いているつもりで、 if x と書いている場合は注意してください
- たとえば、デフォルトの値がNoneになる変数や引数に、何かしら別の値が設定されているかどうかをテストする場合です。
- この「別の値」は、ブール型のコンテクストでは False と評価される(コンテナのような)型かもしれません
not…is …ではなくis not演算子を使いましょう
- これらは機能的に同じですが、後者の方が読みやすく、好ましいです
拡張比較(rich comparion)を使って並び替えを実装する場合、特定の比較を実行するだけの他のコードに依存するよりはむしろ、全ての演算を実装するのがベストです
- 全ての演算 (eq, ne, lt, le, gt, ge)
ラムダ式を直接識別子に結びつける代入文を書くのではなくて常にdef文を使いましょう
- はじめの書き方は、結果として生成される関数オブジェクトの名前が、ラムダではなくて f であると明示的に述べています。
- これは traceback や文字列表現を使うときに役立ちます。代入文を使うと、ラムダ式が提供できる唯一の利点(つまり、大きな式に埋め込めること)を消してしまいます。
def f(x): return 2*x
# 間違い:
f = lambda x: 2*x
BaseExceptionではなくてExceptionから例外を派生させるようにしましょう
- BaseException を直接継承する方法は、例外をキャッチするのが殆どの場合不適切な場合向けに予約されています
例外をキャッチする時は可能なときはいつでも例外を指定しない生のexceptではなく特定の例外を指定するようにしましょう
- 生の except: は SystemExit や KeyboardInterrupt 例外もキャッチしてしまうため、プログラムを Control-C で中断することが難しくなりますし、他の問題をもみ消してしまうかもしれません。
- シグナルのエラーもすべて例外でキャッチしたい場合は、 except Exception: を使ってください (生の except は except BaseException: と同義です)
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
生のexceptを使う場合を次の二つに限ること
- 例外ハンドラが traceback を出力するかロギングする場合。ユーザーは少なくともエラーが起きたことがわかります。
- リソースの後始末が必要な場合、後始末をしたのちに raise を使って上流に例外を伝播させるとき。 この手の問題は、 try…finally の方が適切かもしれません。
リソースがコードの特定の部分だけで使われる場合使った後すぐ信頼できるやり方で後始末ができるようにwith文を使いましょう
関数の中の全てのreturn文は式を返すか全く何も返さないかのどちらかにすべきです
- 式を返しているreturn文が関数の中にある場合、値を何も返さないreturn文は 明示的に return None と書くべきですし、(到達可能であれば)return文を関数の最後に明示的に置くべきです。
def foo(x):
if x >= 0:
return math.sqrt(x)
else:
return None
def bar(x):
if x < 0:
return None
return math.sqrt(x)
# 間違い:
def foo(x):
if x >= 0:
return math.sqrt(x)
def bar(x):
if x < 0:
return
return math.sqrt(x)
文字列に特定のプレフィックスやサフィックスがついているかをチェックするには文字列のスライシングではなく “.startswith() と “.endswith() を使いましょう
- startswith() と endswith() を使うと、綺麗で間違いが起こりにくいコードになります
# 正しい:
if foo.startswith('bar'):
# 間違い:
if foo[:3] == 'bar':
オブジェクトの型の比較は型を直接比較するかわりに常にisinstance()を使うようにすべきです
# 正しい:
if isinstance(obj, int):
# 間違い:
if type(obj) is type(1):
シーケンス(文字列,リスト,タプル)については空のシーケンスがFalseであることを利用しましょう
# 正しい:
if not seq:
if seq:
# 間違い:
if len(seq):
if not len(seq):
行末の空白文字に依存した文字列リテラルを書かないでください
- そういった空白文字は視覚的に判別することができず、エディタによっては (つい最近では reindent.py も) 自動で削除するものもあります
ブール型の値とTrueやFalseを比較するのに==を使うのはやめましょう
# 正しい:
if greeting:
# 間違い:
if greeting == True:
finallyの外に脱出する制御構文を使うのは推奨されません
- 制御構文: return/break/continue
- なぜなら、このような構文は finally の中から伝播する例外を暗黙のうちにキャンセルしてしまうからです
# 間違い:
def foo():
try:
1 / 0
finally:
return 42
関数アノテーションをPEP484とは違うスタイルで使いたいコードについては次のようなコメントを付けておくことを推奨します
- これをファイルの先頭あたりに書いておきます。
- こうすることで、型チェックのプログラムにすべてのアノテーションを無視するように伝えます。(PEP 484 では、型チェックプログラムを黙らせるきめの細かい方法が説明されています)
# type: ignore