PythonはGoogleの主要なスクリプト言語です。このスタイルガイドには、主にpythonのプログラミングガイドラインが含まれています。
バックグラウンド
読者がコードを正確にフォーマットできるように、Vimの構成ファイルを提供しています。 Emacsユーザーの場合は、デフォルト設定のままにしてください。
コードでpylintを実行する
定義:pylintは、Pythonソースコードのバグを見つけるためのツールです。CやC ++などの動的性の低い言語の場合、これらのバグは通常、コンパイラによって検出されます。Pythonのダイナミクスにより、機能、一部の警告は間違っている可能性がありますが、誤った警告は少ないはずです。長所:入力エラー、割り当てられていない変数の使用など、無視しやすいエラーをキャッチできます。短所:pylintは完全ではありません。その利点を活用するには、次のものが必要になる場合があります。 a)その周りにコードを書くb)警告を抑制するc)改善する、またはd)無視する結論:コードでpylintを実行するようにしてください。不正確な警告を抑制して、他の警告が公開されるようにしてください。行コメントを設定することにより、警告を抑制することができます。例:
dict ='something awful' # Bad Idea... pylint: disable=redefined-builtin
ピリント警告は、数値( C0112
など)とシンボリック名( empty-docstring
など)で識別されます。新しいコードを記述したり、既存のコードを更新して警告を処理する場合は、シンボリック名を使用して識別することをお勧めします。 。
警告のシンボル名が理解できない場合は、詳細な説明を追加してください。
この抑制方法を採用する利点は、抑制を簡単に見つけて確認できることです。
コマンド pylint --list-msgs
を使用して、pylint警告のリストを取得できます。コマンド pylint --help-msg = C6409
を使用して、特定のメッセージに関する詳細情報を取得できます。
以前に使用した pylint:disable-msg
と比較して、この記事では pyrint:disable
の使用を推奨しています。
「パラメータ未使用」の警告を抑制するには、パラメータ識別子として「」を使用するか、パラメータ名の前に「unused」を追加します。パラメータ名を変更できない状況が発生した場合は、関数の先頭で「言及」できます。警告を削除します。例:
def foo(a, unused_b, unused_c, d=None, e=None):
_ = d, e return a
パッケージとモジュールにのみインポートを使用する
定義:モジュール間でコードを共有するための再利用メカニズム長所:名前付け管理規則は非常に単純です。各識別子のソースは一貫した方法で示されます。x.Objは、Objオブジェクトがモジュールxで定義されることを意味します。短所:モジュール名まだ競合が発生している可能性があります。一部のモジュール名は長すぎて便利ではありません。結論:パッケージとモジュールをインポートするには、 importx
を使用します。fromximporty
を使用します。ここで、xはパッケージのプレフィックスで、yはプレフィックスのないモジュール名です。インポートする2つのモジュールがyと呼ばれる場合、またはyが長すぎる場合は、 from x import y as z
を使用します。たとえば、モジュール sound.effects.echo
は次のようにインポートできます。
from sound.effects import echo
...
echo.EchoFilter(input, output, delay=0.7, atten=4)
インポート時に相対名を使用しないでください。モジュールが同じパッケージ内にある場合でも、完全なパッケージ名を使用してください。これにより、誤ってパッケージを2回インポートするのを防ぐことができます。
モジュールのフルパス名を使用して、各モジュールをインポートします
長所:モジュール名の競合を回避します。パッケージを見つけやすくなります。短所:パッケージ階層をコピーする必要があるため、コードを展開するのが困難です。結論:すべての新しいコードは、完全なパッケージ名を使用して各モジュールをインポートする必要があります。次のようにインポートする必要があります。
# Reference in code with complete name.import sound.effects.echo# Reference in code with just module name(preferred).from sound.effects import echo
例外は認められますが、注意が必要です
定義:例外は、コードブロックの通常の制御フローから抜け出し、エラーやその他の異常な状態を処理する方法です。利点:通常の操作コードの制御フローがエラー処理コードと混ざり合うことはありません。特定の状態が発生すると、制御フローは複数のフレームをスキップします。たとえば、間違ったコードを実行し続けることなく、1つのステップでN個のネストされた関数からジャンプします。短所:制御フローを混乱させる可能性があります。ライブラリを呼び出すときにエラー状態を見逃しがちです。結論:例外特定の条件を遵守する必要があります。
次のような例外をトリガーします: raise MyException(" Error message ")
または raiseMyException
。2パラメーター形式(raise MyException、 "Error message"
)または古い文字列例外( raise "Error" Error)を使用しないでください。メッセージ "
)。
モジュールまたはパッケージは、組み込みのExceptionクラスから継承する独自のドメイン固有の例外基本クラスを定義する必要があります。モジュールの例外基本クラスは「エラー」と呼ばれる必要があります。
classError(Exception):
pass
except:
ステートメントを使用してすべての例外をキャッチしないでください。また、例外を再トリガーする予定がある場合、または現在のスレッドの最外層にいる場合を除いて、 Exception
または StandardError
をキャッチしないでください(エラーメッセージを出力することを忘れないでください)。 )例外に関しては、Pythonは非常に寛容であり、 except:
はPython構文エラーを含むすべてのエラーを実際にキャッチします。except:
を使用すると、実際のバグを簡単に隠すことができます。
try / exceptionブロック内のコードの量を最小限に抑えます。tryブロックが大きいほど、予期しない例外が発生しやすくなります。この場合、try / exceptブロックは実際のエラーを非表示にします。
finish句を使用して、tryブロックに例外があるかどうかに関係なく実行する必要のあるコードを実行します。これは、ファイルを閉じるなどのリソースのクリーンアップに役立つことがよくあります。
例外をキャッチするときは、コンマの代わりに「as」を使用します。たとえば、
try: raise Errorexcept Error as error: pass
グローバル変数を避ける
定義:モジュールレベルで定義された変数長所:時々役立つ短所:モジュールのインポート時にモジュールレベルの変数が割り当てられるため、モジュールの動作が変更される可能性があります結論:グローバル変数の使用を避け、代わりにクラス変数を使用します。ただし、いくつかあります。例外:
スクリプトのデフォルトオプション。
モジュールレベルの定数。例:PI = 3.14159。定数はすべて大文字で、下線で接続する必要があります。グローバル変数を使用して値をキャッシュしたり、関数として値を返したりすると便利な場合があります。必要に応じて、グローバル変数はモジュール内でのみ使用可能で、モジュールを通過する必要があります。アクセスするパブリック関数を平準化します。
ネストされた/ローカル/内部のクラスまたは関数の使用を奨励する
定義:クラスは、メソッド、関数、またはクラスで定義できます。関数は、メソッドまたは関数で定義できます。囲まれた範囲で定義された変数は、ネストされた関数に対して読み取り専用です。利点:ツールクラスおよび有効スコープでのみ使用されるクラスを定義できます。機能。短所:ネストされたクラスまたはローカルクラスのインスタンスをシリアル化(選択)できません。結論:推奨。
簡単な場合に使用できます
定義:リスト内包表記とジェネレータ式は、map()、filter()、またはlambdaに頼ることなく、リストとイテレータを作成するためのシンプルで効率的な方法を提供します。利点:シンプルリスト内包表記は、他のリスト作成方法よりも明確で単純な場合があります。ジェネレーター式は、リスト全体の作成を回避するため、非常に効率的です。短所:複雑なリスト内包表記またはジェネレーター式は読みにくい場合があります。結論:単純な状況に適しています。 。各部分は別々の行に配置する必要があります:マッピング式、forステートメント、フィルター式。複数のforステートメントまたはフィルター式は禁止されています。複雑な場合でも、ループが使用されます。
Yes:
result =[]for x inrange(10):for y inrange(5):if x * y >10:
result.append((x, y))for x inxrange(5):for y inxrange(5):if x != y:for z inxrange(5):if y != z:yield(x, y, z)return((x,complicated_transform(x))for x inlong_generator_function(parameter)if x is not None) squares =[x * x for x inrange(10)]eat(jelly_bean for jelly_bean in jelly_beans if jelly_bean.color =='black')
No:
result =[(x, y)for x inrange(10)for y inrange(5)if x * y >10]return((x, y, z)for x inxrange(5)for y inxrange(5)if x != y for z inxrange(5)if y != z)
タイプがサポートしている場合は、デフォルトのイテレーターと演算子が使用されます。たとえば、リスト、辞書、ファイルなどです。
定義:辞書やリストなどのコンテナタイプは、デフォルトのイテレータとリレーショナルテスト演算子(内と内ではない)を定義します。利点:デフォルトの演算子とイテレータはシンプルで効率的です。追加のメソッド呼び出しなしで操作を直接表現します。デフォルト演算子を使用する関数はユニバーサルであり、操作をサポートするすべてのタイプに使用できます。デメリット:メソッド名を読み取ってもオブジェクトのタイプを区別できません(たとえば、has_key()は辞書を意味します)。ただし、これも利点です。結論:タイプがサポートしている場合は、リスト、辞書、ファイルなどのデフォルトのイテレーターと演算子を使用します。組み込みタイプもイテレーターメソッドを定義します。これらのメソッドは、リストを返すメソッドよりも優先されます。もちろん、このように繰り返します。コンテナの場合、コンテナを変更することはできません。
Yes:for key in adict:...if key not in adict:...if obj in alist:...for line in afile:...for k, v in dict.iteritems():...
No:for key in adict.keys():...if not adict.has_key(key):...for line in afile.readlines():...
オンデマンドでジェネレーターを使用します。
定義:いわゆるジェネレーター関数とは、yieldステートメントを実行するたびにイテレーターを返し、このイテレーターが値を生成することを意味します。値が生成された後、ジェネレーター関数の実行状態は次の状態まで中断されます。 1回限りの生成長所:呼び出されるたびにローカル変数と制御フローの状態が保存されるため、コードが簡素化されます。一度に一連の値を作成する関数と比較して、ジェネレーターはメモリの使用量が少なくなります。短所:いいえ。結論:推奨事項使用。ジェネレーター関数のdocstringで「Returns:」の代わりに「Yields:」を使用していることに注意してください(翻訳者注:コメントを参照)
単線機能に適しています
定義:ステートメントとは異なり、ラムダは式で匿名関数を定義します。これは、 map()
や filter()
などの高次関数のコールバック関数または演算子を定義するためによく使用されます。長所:便利。短所:より良いローカル関数は読み取りとデバッグがより困難です。関数名がないということは、スタックトレースがより理解しにくいことを意味します。ラムダ関数は通常1つの式しか含まないため、その表現力は制限されます。結論:単一行関数に適しています。コードが60〜80文字を超える場合、通常の(ネストされた)関数として定義することをお勧めします。乗算演算子などの一般的な演算子の場合、ラムダ関数の代わりに operator
モジュールの関数を使用します。たとえば、の代わりに
operator.mulを使用することをお勧めします。ラムダx、y:x * y
。
単線機能に適しています
定義:条件式は、ifステートメントの短い構文規則です。例: x = 1 if cond else 2
。長所:ifステートメントよりも短くて便利。短所:ifステートメントよりも読みにくい。If式が非常に長く、条件を見つけるのが難しい結論:1行の関数に適しています。それ以外の場合は、完全なifステートメントを使用することをお勧めします。
ほとんどの状況に適しています。
定義:関数パラメーターリストの最後に変数の値を指定できます(例: def foo(a、b = 0):
)。パラメーターが1つだけのfooを呼び出すと、bは0に設定されます。2つ取るとパラメータの場合、bの値は2番目のパラメータと等しくなります。利点:多数のデフォルト値を使用する関数が頻繁に発生しますが、場合によっては(まれに)これらのデフォルト値をオーバーライドする必要があります。デフォルトのパラメータ値は、単純なものを提供します。これを実現するために、これらのまれな例外に対して多数の関数を定義する必要はありません。同時に、Pythonはオーバーロードされたメソッドと関数をサポートしていません。デフォルトのパラメーターは、オーバーロードの動作を「偽造」する簡単な方法です。短所:デフォルトのパラメーターモジュールのロード時に1回だけ評価されます。パラメータがリストや辞書などの変数タイプの場合、問題が発生する可能性があります。関数がオブジェクトを変更すると(たとえば、リストに項目を追加する)、デフォルト値が変更されます。結論:使用をお勧めしますが、次のような注意事項があります:関数またはメソッドの定義でデフォルト値として可変オブジェクトを使用しないでください。
Yes: def foo(a, b=None):if b is None:
b =[]
No: def foo(a, b=[]):...
No: def foo(a, b=time.time()): # The time the module was loaded???...
No: def foo(a, b=FLAGS.my_thing): # sys.argv has not yet been parsed......
データメンバーにアクセスして設定するときは、通常、シンプルで軽量なアクセスおよび設定機能を使用します。プロパティの代わりにプロパティを使用することをお勧めします。
定義:メソッド呼び出しをラップする方法。計算量が多くない場合、属性を取得および設定する標準的な方法です。利点:単純な属性アクセスを排除することにより、明示的な取得および設定メソッド呼び出し、読みやすさが向上します。遅延計算が可能です。クラスのインターフェイスはPythonの方法で維持されます。パフォーマンスの観点から、変数への直接アクセスが合理的である場合、アクセスメソッドの追加は簡単で無意味です。プロパティ(プロパティ)を使用します。 )この問題を回避できます。将来的には、インターフェイスを壊さずにアクセスメソッドを追加することもできます。欠点:プロパティはgetおよびsetメソッド宣言の後に指定されるため、ユーザーは次のコードに注意する必要があります。 :setとgetはプロパティに使用されます( @ property
デコレータで作成された読み取り専用プロパティを除く)。オブジェクトクラスから継承する必要があります。演算子のオーバーロードなどの副作用を隠す可能性があります。継承により、人が作成される可能性があります。混乱している結論:通常、アクセスまたは設定メソッドを使用してデータにアクセスまたは設定することに慣れています。これらはシンプルで軽量です。ただし、新しいコードでプロパティを使用することをお勧めします。読み取り専用プロパティは、 @ property
デコレータを使用して作成する必要があります。サブクラスがプロパティをオーバーライドしない場合、プロパティの継承が明確に見えない可能性があります。したがって、ユーザーは、サブクラスのオーバーロードされたメソッドがプロパティによって呼び出されるように、アクセスメソッドが間接的に呼び出されるようにする必要があります(テンプレートメソッドの設計パターンを使用)。
Yes:import math classSquare(object):"""A square with two properties: a writable area and a read-only perimeter. To use:>>> sq =Square(3)>>> sq.area
9>>> sq.perimeter
12>>> sq.area =16>>> sq.side
4>>> sq.perimeter
16""" def __init__(self, side):
self.side = side def __get_area(self):"""Calculates the 'area' property."""return self.side **2 def ___get_area(self):"""Indirect accessor for 'area' property."""return self.__get_area() def __set_area(self, area):"""Sets the 'area' property."""
self.side = math.sqrt(area) def ___set_area(self, area):"""Indirect setter for 'area' property."""
self._SetArea(area) area =property(___get_area, ___set_area,
doc="""Gets or sets the area of the square.""") @property
def perimeter(self):return self.side *4
( 翻訳者注:正直なところ、このサンプルコードは非常に不適切だと思いますが、それほど苦痛である必要がありますか?)
可能な限り暗黙のfalseを使用する
定義:Pythonは、ブールコンテキストで特定の値をfalseと評価します。単純な直感によれば、すべての「空の」値はfalseと見なされます。したがって、0、None、[]、{}、 ""どちらも誤りと見なされます。長所:Pythonブール値を使用する条件付きステートメントは、読みやすく、間違いを犯しにくいです。ほとんどの場合、高速です。短所:C / C ++開発者にとっては、少し奇妙に思えるかもしれません。結論:可能な限り暗黙のfalseを使用します。たとえば、次のようになります。 if foo!= []:
の代わりに if foo:
を使用します。ただし、次の点に注意する必要があります。
==または!=を使用して、Noneなどの単一の項目を比較しないでください。使用するかどうかを指定してください。注:「ifx:」と書く場合、実際には「ifxがNone」ではないことを意味します。デフォルト値がNoneである変数またはパラメーターが別の値に設定されているかどうかをテストする場合。この値は、ブールセマンティクスではfalseである可能性があります。
ブール値をfalseと比較するために==を使用しないでください。代わりに if not x:
を使用してください。falseとNoneを区別する必要がある場合は、 if not x and x is not None:
のようなステートメントを使用する必要があります。シーケンス(文字列、リスト、タプル)の場合、空のシーケンスはfalseであることに注意してください。したがって、 if not seq:
または if seq:
は、 if len(seq):
または `if not len(seq):よりも優れています。 「良くなるために。
整数を処理する場合、暗黙のfalseの使用がゲインを上回る可能性があります(つまり、誤ってNoneを0として扱います)。整数であることがわかっている値(len()の戻り結果ではない)を0と比較できます。
Yes:if not users: print 'no users'if foo ==0: self.handle_zero()if i %10==0: self.handle_multiple_of_ten()
No:iflen(users)==0: print 'no users'if foo is not None and not foo:
self.handle_zero()if not i %10:
self.handle_multiple_of_ten()
'0'(文字列)はtrueとして扱われることに注意してください。
可能な限り、文字列モジュールの代わりに文字列メソッドを使用します。apply()の代わりに関数呼び出し構文を使用します。filter()、map()、reduce()の代わりにリスト内包表記とforループを使用します。
定義:現在のバージョンのPythonは、人々が通常好む代替手段を提供します。結論:これらの機能をサポートしないバージョンのPythonは使用しないため、新しいメソッドを使用しない理由はありません。
Yes: words = foo.split(':')[x[1]for x in my_list if x[2]==5]map(math.sqrt, data) # Ok. No inlined lambda expression.fn(*args,**kwargs)
No: words = string.split(foo,':')map(lambda x: x[1],filter(lambda x: x[2]==5, my_list))apply(fn, args, kwargs)
推奨用途
定義:ネストされたPython関数は、外部関数で定義された変数を参照できますが、それらに値を割り当てることはできません。変数バインディングの分析では、静的プログラムテキストに基づく字句スコープを使用します。ブロック内の特定のブロックに対して名前を割り当てると、Pythonは、割り当て前の処理を含め、名前へのすべての参照をローカル変数として扱います。グローバル宣言が検出された場合、名前はグローバル変数として扱われます。この機能の使用例:
def get_adder(summand1):"""Returns a function that adds numbers to a given number."""
def adder(summand2):return summand1 + summand2 return adder
( 翻訳者注:この例は少し奇妙です。次のようにこの関数を使用する必要があります: sum = get_adder(summand1)(summand2)
)
利点:通常、より明確でエレガントなコードをもたらすことができます。特に経験豊富なLispおよびScheme(およびHaskell、MLなど)プログラマーは安心します。欠点:混乱を招くバグにつながる可能性があります。たとえば、以下はPEPに基づいています。 -0227例:
i = 4def foo(x):
def bar():
print i, # ...
# A bunch of code here
# ... for i in x: # Ah, i *is* local to Foo, so this is what Bar sees
print i,bar()
したがって、 foo([1、2、3])
は、 1 2 34
ではなく 1 2 33
を出力します。
( 翻訳者注:xはリストであり、forループは実際にxの値をiに順番に割り当てます.iへの割り当ては暗黙的に行われ、foo関数本体全体のiはbarを含むローカル変数として扱われます()にあるもの。これは、C ++などの静的言語とはまだ大きく異なります。)
結論:使用を奨励します。
利点が明らかな場合は、デコレータを賢明かつ慎重に使用してください。
定義:関数とメソッドに使用されるデコレータ(つまり、@ mark)。最も一般的なデコレータは@classmethodと@staticmethodで、通常の関数をクラスメソッドまたは静的メソッドに変換するために使用されます。ただし、デコレータ構文ではユーザーも使用できます。カスタムデコレータ。特に、関数 my_decorator
の場合、次の2つのコードは同等です。
classC(object): @my_decorator
def method(self):
# method body ...
classC(object):
def method(self):
# method body ...
method =my_decorator(method)
利点:関数にいくつかの変換を適切に指定します。この変換により、コードの重複が減り、既存の関数が変更されないようになります(不変条件が適用されます)など。欠点:デコレータは、関数のパラメータまたは戻り値に対して任意の操作を実行できます。驚くべき隠された動作を引き起こす可能性があります。さらに、デコレータはインポート時に実行されます。デコレータコードの障害から回復することはさらに不可能です。結論:利点が明らかな場合は、デコレータを賢明かつ慎重に使用してください。デコレータは従う必要があります。関数と同じインポートおよび命名規則。デコレータのpythonドキュメントには、関数がデコレータであることが明確に記載されている必要があります。デコレータのユニットテストを記述してください。デコレータ自体が外界に依存しないようにしてください(つまり、ファイルやソケットなどに依存しないでください)。デコレータの実行中( pydoc
または他のツールによってインポートされる)にこれらのリソースが利用できない可能性があるため、データベース接続など)。有効なパラメータで呼び出されたデコレータがすべての場合に成功することを確認する必要があります。デコレータは一種です。 「トップレベルコード」の特殊な形式。後でメインのトピックを参照してください。
組み込み型の原子性に依存しないでください。
辞書などのPythonの組み込み型にはアトミックな操作があるように見えますが、それでもアトミックではない場合があり(つまり、__ hash__または__eq__がPythonメソッドとして実装されている場合)、そのアトミック性は信頼できません。また、アトミック変数の割り当てを当てにすることもできません(これは辞書に依存するため)。
スレッド間のデータ通信の方法として、Queueモジュールの Queue
データタイプを使用します。さらに、スレッドモジュールとそのロックプリミティブを使用します。条件変数の適切な使用法を知っているので、threading.Conditionを使用できます。
低レベルのロックを置き換えるため。
これらの機能の使用は避けてください
定義:Pythonは非常に柔軟な言語であり、メタクラス、バイトコードアクセス、オンザフライコンパイル、動的継承、オブジェクトの親クラスなど、多くの優れた機能を提供します。再定義(オブジェクトの親の変更)、インポートハック、リフレクション、システム内部の変更など。長所:強力な言語機能により、コードがよりコンパクトになります。短所:これらを使用すると非常に便利です。 「かっこいい」機能は非常に魅力的ですが、絶対に必要というわけではありません。凝ったトリックを使用するコードは、読み取りとデバッグがより困難になります。最初は(元の作成者にとって)良いかもしれませんが、コードを確認すると、それらよりも優れている可能性があります。長くて単純なコードは理解するのがより困難です。結論:コードでこれらの機能を避けてください。
行の終わりにセミコロンを追加したり、同じ行に2つのコマンドを配置するためにセミコロンを使用したりしないでください。
1行あたり80文字以下
例外:長いインポートモジュールステートメントコメントのURLの行を接続するためにバックスラッシュを使用しないでください。
Pythonは、括弧、角括弧、中括弧を暗黙的に連結します。この機能を利用できます。必要に応じて、式の前後に括弧のペアを追加できます。
Yes:foo_bar(self, width, height, color='black', design=None, x='foo',
emphasis=None, highlight=0)if(width ==0 and height ==0 and
color =='red' and emphasis =='strong'):
テキスト文字列が1行に収まらない場合は、括弧を使用して暗黙的な行連結を実現できます。
x =('This will build a very long long ''long long long long long long string')
コメントでは、必要に応じて、長いURLを1行に入れます。
Yes: # See details at
# http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html
No: # See details at
# http://www.example.com/us/developer/documentation/api/content/\
# v2.0/csv_file_name_extension_full_specification.html
上記の例の要素のインデントに注意してください。この記事のインデントセクションに説明があります。
NingQuewuは括弧を無差別に使用します
行連結の実装に使用する場合を除き、returnステートメントまたは条件ステートメントで括弧を使用しないでください。ただし、タプルの前後に括弧を使用することは可能です。
Yes:if foo:bar()while x:
x =bar()if x and y:bar()if not x:bar()return foo for(x, y)in dict.items():...
No:if(x):bar()ifnot(x):bar()return(foo)
4つのスペースを使用してコードをインデントします
タブを使用したり、タブとスペースを混在させたりしないでください。行を連結するには、行で折り返された要素を垂直方向に揃えるか(行の長さのセクションの例を参照)、4つのスペース(この場合は最初の行)のぶら下げインデントを使用する必要があります。パラメータがあってはなりません):
Yes: # Aligned with opening delimiter
foo =long_function_name(var_one, var_two,
var_three, var_four) # Aligned with opening delimiter in a dictionary
foo ={
long_dictionary_key: value1 +
value2,...} # 4-space hanging indent; nothing on first line
foo =long_function_name(
var_one, var_two, var_three,
var_four) # 4-space hanging indent in a dictionary
foo ={
long_dictionary_key:
long_dictionary_value,...}
No: # Stuff on first line forbidden
foo =long_function_name(var_one, var_two,
var_three, var_four) # 2-space hanging indent forbidden
foo =long_function_name(
var_one, var_two, var_three,
var_four) # No hanging indent in a dictionary
foo ={
long_dictionary_key:
long_dictionary_value,...}
トップレベル定義間の2つの空白行、およびメソッド定義間の1つの空白行
関数やクラスの定義など、最上位の定義の間には2行の空白行が必要です。メソッド定義、クラス定義、および最初のメソッドの間には空白行が必要です。関数またはメソッドで、関数またはメソッドに場所が見つかった場合は、空白行を残す必要があります。
標準のタイプ設定規則に従って、句読点の両側にスペースを使用します
括弧内にスペースを入れないでください。
Yes:spam(ham[1],{eggs:2},[])
No:spam( ham[1],{ eggs:2},[])
カンマ、セミコロン、コロンの前にスペースを入れないでください。ただし、それらの後にスペースを追加する必要があります(行末を除く)。
Yes:if x ==4: print x, y
x, y = y, x
No:if x ==4: print x , y
x , y = y , x
パラメータリスト、インデックス、またはスライスの開始括弧の前にスペースを追加しないでください。
Yes:spam(1)
no:spam(1)
Yes: dict['key']= list[index]
No: dict ['key']= list [index]
割り当て(=)、比較(==、<、>、!=、<>、<=、> =、in、not in、is、is not)などのバイナリ演算子の両側にスペースを追加します。ブール値(and、or、not)。算術演算子の両側のスペースの使用方法については、自分で判断する必要がありますが、両側が一貫している必要があります。
Yes: x ==1
No: x<1
「=」を使用してキーワードパラメータまたはデフォルトのパラメータ値を示す場合は、両側にスペースを使用しないでください。
Yes: def complex(real, imag=0.0):returnmagic(r=real, i=imag)
No: def complex(real, imag =0.0):returnmagic(r = real, i = imag)
複数の行の間でマークを垂直方向に揃えるためにスペースを使用しないでください。これはメンテナンスの負担になります(:、#、=などに適用されます)。
Yes:
foo =1000 # comment
long_name =2 # comment that should not be aligneddictionary ={"foo":1,"long_name":2,}
No:
foo =1000 # comment
long_name =2 # comment that should not be aligneddictionary ={"foo":1,"long_name":2,}
ほとんどの.pyファイルは#!で始まる必要はありません。PEP-394によると、プログラムのメインファイルは#!/ usr / bin / python2または#!/ usr / bin / python3で始まる必要があります。
( 翻訳者注:コンピュータサイエンスでは、Shebang(Hashbangとも呼ばれます)は、ポンド記号と感嘆符で構成される文字列(#!)であり、テキストファイルの最初の行の最初の2文字に表示されます。ファイル内Shebangが存在する場合、Unixのようなオペレーティングシステムのプログラムローダーは、Shebangの内容を分析し、これらの内容をインタープリター命令として使用し、命令を呼び出し、Shebangを含むファイルパスをインタープリターのパラメーターとして使用します。たとえば、コマンド#!/ bin / shで始まるファイルは、実行時に実際には/ bin / shプログラムを呼び出します。)
#! 最初はカーネルがPythonインタープリターを見つけるのを助けるために使用されますが、モジュールをインポートするときに無視されます。したがって、直接実行されるファイルに#!。を追加するだけで済みます。
モジュール、関数、メソッド、およびインラインコメントには正しいスタイルを使用してください
**Docstring **
Pythonには、独自のコメント方法があります。docstringを使用します。docstringは、パッケージ、モジュール、クラス、または関数の最初のステートメントです。これらの文字列は、オブジェクトの__doc__メンバーによって自動的に抽出され、pydocになります。使用済み(モジュールでpydocを実行して、どのように表示されるかを確認できます)。docstringの規則では、三重二重引用符 "" "(PEP-257)を使用します。docstringはこのように構成されています:最初に、ピリオド、疑問符、または感嘆符で終わる要約行があります(または、docstringは1行だけです)。次に、空白行があります。次に、残りのdocstringがあります。これは、docstringの最初の行と同じである必要があります。行の最初の引用符が揃えられます。以下に、docstringのフォーマット仕様があります。
モジュール
各ファイルにはライセンステンプレートが含まれている必要があります。プロジェクトで使用されるライセンス(Apache 2.0、BSD、LGPL、GPLなど)に従って、適切なテンプレートを選択します。
関数とメソッド
以下で参照する関数には、関数、メソッド、およびジェネレーターが含まれます。
次の条件を満たす場合を除き、関数にはdocstringが必要です。
外からは見えない
とても短い
わかりやすい
docstringには、入力と出力だけでなく、関数の機能の詳細な説明が含まれている必要があります。一般に、複雑なアルゴリズムを除いて、「実行方法」を記述してはなりません。docstringは、他の誰かが関数を呼び出すコードを記述したときに十分な情報を提供する必要があります。現時点では、彼はコード行を読む必要はなく、docstringを見るだけです。複雑なコードの場合、コードの横にコメントを追加する方が、docstringを使用するよりも意味があります。
機能のいくつかの側面を特定のセクションで説明する必要があります。これらの側面については、以下で説明します。各セクションはタイトル行で開始する必要があります。タイトル行はコロンで終了する必要があります。タイトル行を除いて、セクションの残りの部分は2スペースインデントされています。
Args:各パラメーターの名前をリストし、名前の後にコロンとスペースを使用してパラメーターの説明を区切ります。説明が長すぎて1行で80文字を超えることができない場合は、2つまたは4つのスペースのぶら下げインデントを使用します(およびファイルの残りの部分は一貫している必要があります)説明には、必要なタイプと意味を含める必要があります。関数が* foo(可変長パラメーターリスト)または** bar(任意のキーワードパラメーター)を受け入れる場合は、* fooおよび**を詳細にリストする必要があります。 bar.Returns :(またはYields:ジェネレーターの場合)は、戻り値のタイプとセマンティクスを記述します。関数がNoneを返す場合、この部分は省略できます。Raises:インターフェイスに関連するすべての例外を一覧表示します。
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):"""Fetches rows from a Bigtable. Retrieves rows pertaining to the given keys from the Table instance
represented by big_table. Silly things may happen if
other_silly_variable is not None. Args:
big_table: An open Bigtable Table instance.
keys: A sequence of strings representing the key of each table row
to fetch.
other_silly_variable: Another optional variable, that has a much
longer name than the other args, and which does nothing. Returns:
A dict mapping keys to the corresponding table row data
fetched. Each row is represented as a tuple of strings. For
example:{'Serak':('Rigel VII','Preparer'),'Zim':('Irk','Invader'),'Lrrr':('Omicron Persei 8','Emperor')} If a key from the keys argument is missing from the dictionary,
then that row was not found in the table. Raises:
IOError: An error occurred accessing the bigtable.Table object."""
pass
クラス
クラスの定義の下に、クラスを説明するdocstringが必要です。クラスにパブリック属性(属性)がある場合、ドキュメントには属性セクションが必要です。また、関数パラメーターと同じ形式に従う必要があります。 。
classSampleClass(object):"""Summary ofclasshere. Longer classinformation....
Longer classinformation.... Attributes:
likes_spam: A boolean indicating if we like SPAM or not.
eggs: An integer count of the eggs we have laid."""def __init__(self, likes_spam=False):"""Inits SampleClass with blah."""
self.likes_spam = likes_spam
self.eggs = 0def public_method(self):"""Performs operation blah."""
コメントのブロックとコメントの行
コメントを書く上で最も重要なことは、コードのトリッキーな部分です。次のコードレビューで説明する必要がある場合は、今すぐコメントする必要があります。複雑な操作の場合は、操作を開始する前にいくつか書く必要があります。行コメント:自明ではないコードの場合は、行の最後にコメントを追加する必要があります。
# We use a weighted dictionary search to find out where i is in# the array. We extrapolate position based on the largest num# in the array and the array size and then do binary search to# get the exact number.if i &(i-1)==0: # true iff i is a power of2
読みやすさを向上させるために、コメントはコードに少なくとも2つのスペースを残す必要があります。
一方、コードを説明しないでください。コードを読んでいる人があなたよりもPythonをよく理解していると仮定すると、彼はあなたのコードが何をしているのかを知らないだけです。
# BAD COMMENT: Now go through the b array and make sure whenever i occurs# the next element is i+1
クラスが他のクラスから継承しない場合、オブジェクトから明示的に継承します。ネストされたクラスについても同じことが言えます。
Yes:classSampleClass(object):
passclass OuterClass(object):classInnerClass(object):
passclass ChildClass(ParentClass):"""Explicitly inherits from another class already."""
No:classSampleClass:
passclass OuterClass:classInnerClass:
pass
object
から継承することは、プロパティを適切に機能させ、PEP-3000の特別な潜在的な非互換性からコードを保護することです。これは、いくつかの特別なメソッドも定義します。これらのメソッドは、 __new __、__ init __、__ delattr __、__ getattribute __、__ setattr __、__ hash __、__ repr__、および__str__
を含むオブジェクトのデフォルトのセマンティクスを実装します。
パラメータがすべて文字列の場合でも、%演算子またはフォーマット方法を使用して文字列をフォーマットします。ただし、一般化することはできません。+と%のどちらかを判断する必要があります。
Yes: x = a + b
x ='%s, %s!'%(imperative, expletive)
x ='{}, {}!'.format(imperative, expletive)
x ='name: %s; score: %d'%(name, n)
x ='name: {}; score: {}'.format(name, n)
No: x ='%s%s'%(a, b) # use +inthiscase
x ='{}{}'.format(a, b) # use +inthiscase
x = imperative +', '+ expletive +'!'
x ='name: '+ name +'; score: '+str(n)
ループ内で+および+ =演算子を使用して文字列を累積することは避けてください。文字列は不変であるため、これを行うと、不要な一時オブジェクトが作成され、線形ランタイムではなく2次ランタイムが発生します。各サブストリングをリストに追加し、ループの終了後に .join
を使用してリストに参加できます(各サブストリングを cStringIO.StringIO
キャッシュに書き込むこともできます)。
Yes: items =['<table>']for last_name, first_name in employee_list:
items.append('<tr><td>%s, %s</td></tr>'%(last_name, first_name))
items.append('</table>')
employee_table =''.join(items)
No: employee_table ='<table>'for last_name, first_name in employee_list:
employee_table +='<tr><td>%s, %s</td></tr>'%(last_name, first_name)
employee_table +='</table>'
同じファイルで、文字列の引用符の使用の一貫性を保ちます。一重引用符または二重引用符のいずれかを使用して文字列を引用し、同じファイルで引き続き使用します。文字列で別の種類の引用符を使用して、文字列での使用は避けてください。GPyLintはこのチェックを追加しました。
( 翻訳者注:GPyLintはタイプミスの疑いがあり、PyLintである必要があります。)
Yes:Python('Why are you hiding your eyes?')Gollum("I'm scared of lint errors.")Narrator('"Good!" thought a happy Python reviewer.')
No:Python("Why are you hiding your eyes?")Gollum('The lint. It burns. It burns us.')Gollum("Always the great lint. Watching. Watching.")
複数行の文字列には、トリプルシングルクォーテーションマークの代わりにトリプルダブルクォーテーションマーク "" "を使用します。プロジェクトでシングルクォーテーションマークを使用して文字列を引用する場合に限り、トリプル
'を非ドキュメント文字列として使用できます。複数行の文字列は参照を識別するために使用されます。docstringは三重の二重引用符 "" "を使用する必要があります。ただし、複数行の文字列はプログラムの他の部分のインデントと矛盾するため、通常は暗黙的な行の連結を使用する方が明確です。
Yes:print("This is much nicer.\n""Do it this way.\n")
No: print """This is pretty ugly.
Don't dothis."""
ファイルとソケットの最後で、明示的に閉じます。
ファイルに加えて、ソケットまたは他のファイルのようなオブジェクトは、必要のないときに開かれ、次のような多くの副作用があります。
さらに、ファイルオブジェクトが破棄されたときにファイルとソケットが自動的に閉じられることを想像するのは非現実的です。ファイルオブジェクトのライフサイクルをファイルの状態にバインドしようとするのは非現実的です。次の理由によります。
ファイルを管理するには、「with」ステートメントを使用することをお勧めします。
withopen("hello.txt")as hello_file:for line in hello_file: print line
「with」ステートメントの使用をサポートしないファイルのようなオブジェクトの場合は、contextlib.closeing()を使用します。
import contextlibwith contextlib.closing(urllib.urlopen("http://www.python.org/"))as front_page:for line in front_page: print line
LegacyAppEngineのPython2.5コードで「with」ステートメントを使用する場合は、「from __future__importwith_statement」を追加する必要があります。
一時的なコードにはTODOコメントを使用します。これは短期的な解決策です。完璧ではありませんが、十分です。
TODOコメントには、すべての先頭に文字列「TODO」が含まれ、その後に名前、電子メールアドレス、またはその他の識別子が括弧で囲まれている必要があります。その後、オプションのコロンが含まれている必要があります。何をすべきか主な目的は、コメントを追加する人がそれを検索できるように(そして必要に応じて詳細を提供できるように)統一されたTODO形式を持つことです。TODOコメントを書くことは、書く人が自分で問題を解決することを保証しません。 TODOを書いたので、名前を書いてください。
# TODO([email protected]): Use a "*" here for string repetition.# TODO(Zeke) Change this to use relations.
TODOが「将来何かをする」という形式の場合は、指定した日付(「2009年11月に解決」)または特定のイベント(「すべての顧客がXML要求を処理できるようになるまで待つ)」を含めるようにしてください。これらのコードを削除してください」)。
各インポートは独自の行にある必要があります
Yes:import os import sys
No:import os, sys
インポートは常にファイルの先頭、モジュールのコメントとdocstringの後、モジュールのグローバル変数と定数の前に配置する必要があります。インポートは、最も一般的なものから最も一般的でないものの順にグループ化する必要があります。
各グループでは、大文字と小文字を区別せずに、各モジュールの完全なパッケージパスに従って字句的に並べ替える必要があります。
import foo
from foo import bar
from foo.bar import baz
from foo.bar import Quux
from Foob import ar
通常、各ステートメントは独自の行にある必要があります
ただし、テスト結果とテストステートメントが1行に収まる場合は、同じ行に配置することもできます。ifステートメントの場合は、他にない場合にのみ実行できます。特に、 try / except
を使用してこれを実行しないでください。 tryとexceptを同じ行に配置できないためです。
Yes:if foo:bar(foo)
No:if foo:bar(foo)else:baz(foo)try:bar(foo) except ValueError:baz(foo)try:bar(foo) except ValueError:baz(foo)
Pythonでは、些細で重要性の低いアクセス関数の場合、追加の関数呼び出しオーバーヘッドを回避するために、パブリック変数を直接使用してそれらを置き換える必要があります。関数を追加するときは、プロパティを使用して構文を維持できます。一貫性。
( 翻訳者注:カプセル化を重視するオブジェクト指向のプログラマーは、教育を受けているため、これを見るとうんざりする可能性があります。すべてのメンバー変数はプライベートである必要があります。実際、少し面倒です。Pythonの哲学を受け入れてみてください。バー)
一方、アクセスがより複雑な場合、または可変アクセスオーバーヘッドが大きい場合は、 get_foo()
や set_foo()
などの関数呼び出しを使用する必要があります。前のコードの動作でプロパティを介したアクセスが許可されている場合、次に、新しいアクセス関数をプロパティにバインドしないでください。このようにして、古いメソッドを介して変数にアクセスしようとするコードは実行されず、ユーザーは複雑さが変更されたことに気付くでしょう。
module_name, package_name, ClassName, method_name, ExceptionName, function_name, GLOBAL_VAR_NAME, instance_var_name, function_parameter_name, local_var_name.
避けるべき名前
カウンターとイテレーターを除く、1文字の名前。
パッケージ/モジュール名のハイフン(-)
二重下線で開始および終了する名前(__init__などのPythonによって予約済み)
命名規則
いわゆる「内部」とは、モジュールでのみ使用可能であるか、クラスで保護またはプライベートであるという意味です。
モジュール変数または関数が保護されていることを示すために、単一の下線(_)で開始します(import * fromが使用されている場合は含まれません)。
二重下線(__)で始まるインスタンス変数またはメソッドは、クラス内のプライベートを示します。
関連するクラスとトップレベルの関数を同じモジュールに配置します。Javaとは異なり、1つのクラスを1つのモジュールに制限する必要はありません。
クラス名には大文字の単語(CapWords、Pascalスタイルなど)を使用しますが、モジュール名には小文字と下線を付ける必要があります(lower_with_under.pyなど)。ただし、CapWords.pyなどを使用する既存のモジュールはすでに多数あります。命名しますが、モジュール名がクラス名と同じであると混乱する可能性があるため、現在は推奨されていません。
Pythonの父であるGuidoが推奨するガイドライン
Type | Public | Internal |
---|---|---|
Modules | lower_with_under | _lower_with_under |
Packages | lower_with_under | |
Classes | CapWords | _CapWords |
Exceptions | CapWords | |
Functions | lower_with_under() | _lower_with_under() |
Global/Class Constants | CAPS_WITH_UNDER | _CAPS_WITH_UNDER |
Global/Class Variables | lower_with_under | _lower_with_under |
Instance Variables | lower_with_under | _lower_with_under (protected) or __lower_with_under (private) |
Method Names | lower_with_under() | _lower_with_under() (protected) or __lower_with_under() (private) |
Function/Method Parameters | lower_with_under | |
Local Variables | lower_with_under |
スクリプトとして使用することを目的としたファイルでもインポート可能である必要があります。また、単純なインポートによってスクリプトの主な機能が実行されることはありません。これは副作用です。主な機能はメインに配置する必要があります。 () 関数。
Pythonでは、pydocおよびユニットテストではモジュールがインポート可能である必要があります。モジュールのインポート時にメインプログラムがインポートされないように、コードはメインプログラムを実行する前に常に if __name__ == '__ main __'
をチェックする必要があります。実施した。
def main():...if __name__ =='__main__':main()
すべてのトップレベルコードは、モジュールのインポート時に実行されます。pydocの使用時に、関数を呼び出したり、オブジェクトを作成したり、実行してはならない操作を実行したりしないように注意してください。
出典:開発者技術最前線
開発者は投稿を提出することを歓迎します
[ 無料の小さな秘密のサークルの資格があなたを参加に招待します](http://mp.weixin.qq.com/s?__biz=MzIyMjQ0MTU0NA==&mid=2247485122&idx=2&sn=5bd73f58ed7cc0243f63cced6e502344&chksm=e82c3fe5df5bb5ccee
Recommended Posts