aboutsummaryrefslogtreecommitdiff
path: root/docs/ja/coding_conventions_python.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/ja/coding_conventions_python.md')
-rw-r--r--docs/ja/coding_conventions_python.md331
1 files changed, 331 insertions, 0 deletions
diff --git a/docs/ja/coding_conventions_python.md b/docs/ja/coding_conventions_python.md
new file mode 100644
index 000000000..d8d4a3150
--- /dev/null
+++ b/docs/ja/coding_conventions_python.md
@@ -0,0 +1,331 @@
1# コーディング規約 (Python)
2
3<!---
4 original document: 0.9.19:docs/coding_conventions_python.md
5 git diff 0.9.19 HEAD -- docs/coding_conventions_python.md | cat
6-->
7
8私たちのスタイルの大部分は PEP8 に従いますが、神経質にならないように幾つかのローカルな変更を加えています。
9
10* サポートされる全てのプラットフォームとの互換性のために、Python 3.6 を対象にしています。
11* 4つのスペース (ソフトタブ) を使ってインデントします
12* 充分なコメントを書くことを推奨します
13 * コメントを機能を説明するストーリーと考えて下さい
14 * 特定の決定がなされた理由を充分なコメントで説明してください。
15 * 分かり切ったコメントは書かないでください
16 * 分かり切ったコメントであるか確信できない場合は、コメントを含めてください。
17* 全ての関数について、役に立つ docstring を必要とします。
18* 一般的に、行を折り返さないで、必要なだけ長くすることができます。行を折り返すことを選択した場合は、76列を超えて折り返さないでください。
19* 私たちの慣習の幾つかは、Python 使いでは無い人にコードベースをより身近にするために、python コミュニティに広まっているものとは競合しています。
20
21# YAPF
22
23コードを整形するために [yapf](https://github.com/google/yapf) を使うことができます。[setup.cfg](setup.cfg) で設定を提供しています。
24
25# インポート
26
27`import ...` や `from ... import ...` をいつ使うかについての厳密なルールはありません。理解しやすさと保守性が究極の目的です。
28
29一般的に、コードを短く理解しやすくするためにモジュールから特定の関数とクラス名をインポートする方が望ましいです。これにより、名前が曖昧になることがあります。代わりにモジュールをインポートするようにします。互換性のあるモジュールをインポートする時を除いて、インポートする時は "as" キーワードを避けるべきです。
30
31インポートは各モジュール1行にする必要があります。標準的な python ルールに従って、インポート文をシステム、サードパーティ、ローカルにグループ化します。
32
33`from foo import *` を使わないでください。代わりにインポートしたいオブジェクトのリストを指定するか、モジュール全体をインポートします。
34
35## インポートの例
36
37良い:
38
39```
40from qmk import effects
41
42effects.echo()
43```
44
45悪い:
46
47```
48from qmk.effects import echo
49
50echo() # echoがどこから来たのかが不明瞭です
51```
52
53良い:
54
55```
56from qmk.keymap import compile_firmware
57
58compile_firmware()
59```
60
61良いですが、上の方がより良いです:
62
63```
64import qmk.keymap
65
66qmk.keymap.compile_firmware()
67```
68
69# 命令文
70
71各行1文としてください。
72
73可能な場合(例えば `if foo: bar`)でも、2つの文を1行にまとめないでください。
74
75# 命名
76
77`module_name`, `package_name`, `ClassName`, `method_name`, `ExceptionName`, `function_name`, `GLOBAL_CONSTANT_NAME`, `global_var_name`, `instance_var_name`, `function_parameter_name`, `local_var_name`.
78
79関数名、変数名 およびファイル名は説明的でなければなりません; 略語を避けます。特に、プロジェクト外の読み手に曖昧あるいは馴染みのない略語を使わず、単語内の文字を削除して略さないでください。
80
81常に .py のファイル名の拡張子を使います。ダッシュを使わないでください。
82
83## 避けるべき名前
84
85* カウンタあるいはイテレータ以外の1文字の名前。try/except 文では例外の識別子として `e` を使うことができます。
86* パッケージ/モジュール名内のダッシュ (`-`)
87* `__double_leading_and_trailing_underscore__` (2つのアンダースコアで始まる名前と終わる名前、Python で予約済み)
88
89# Docstring
90
91docstring の一貫性を維持するために、以下のガイドラインを設定しました。
92
93* マークダウン(Markdown)形式の使用
94* 常に少なくとも1つの改行を含む3つのダブルクォートの docstring を使ってください: `"""\n"""`
95* 最初の行は、関数が行うことの短い (70文字未満) 説明です。
96* docstring が更に必要な場合は、説明と残りの間に空白行を入れます。
97* 開始の3つのダブルクォートと同じインデントレベルでインデント行を始めます
98* 以下で説明する形式を使って全ての関数の引数について記述します
99* Args:、Returns: および Raises: が存在する場合、それらは docstring の最後の3つの要素で、それぞれ空白行で区切られなければなりません。
100
101## 簡単な docstring の例
102
103```
104def my_awesome_function():
105 """1970 Jan 1 00:00 UTC からの秒数を返します。
106 """
107 return int(time.time())
108```
109
110## 複雑な docstring の例
111
112```
113def my_awesome_function():
114 """1970 Jan 1 00:00 UTC からの秒数を返します。
115
116 この関数は常に整数の秒数を返します。
117 """
118 return int(time.time())
119```
120
121## 関数の引数の docstring の例
122
123```
124def my_awesome_function(start=None, offset=0):
125 """1970 Jan 1 00:00 UTC からの秒数を返します。
126
127 この関数は常に整数の秒数を返します。
128
129
130 Args:
131 start
132 1970 Jan 1 00:00 UTC の代わりの開始時間
133
134 offset
135 最初の引数からこの秒数が引かれた答えを返します
136
137 Returns:
138 秒数を表す整数。
139
140 Raises:
141 ValueError
142 `start` あるいは `offset` が正の数ではない場合
143 """
144 if start < 0 or offset < 0:
145 raise ValueError('start and offset must be positive numbers.')
146
147 if not start:
148 start = time.time()
149
150 return int(start - offset)
151```
152
153# 例外
154
155例外は例外的な状況を処理するために使われます。フローの制御のために使われるべきではありません。これは Python の「許しを請う」という規範からの逸脱です。例外をキャッチする場合、異常な状況を処理する必要があります。
156
157何らかの理由で全ての例外のキャッチを使う場合は、cli.log を使って例外とスタックトレースを記録する必要があります。
158
159try/except ブロックをできるだけ短くします。多数の try 文が必要な場合は、コードを再構成する必要があるかもしれません。
160
161# タプル
162
1631項目のタプルを定義する場合、タプルを使用していることが明らかになるように、常に末尾のカンマを含めます。暗黙的な1項目のタプルのアンパックに頼らないでください。明確なリストを使う方が良いです。
164
165これはよく使用される printf 形式の書式文字列を使う場合に、特に重要です。
166
167# リストと辞書
168
169シーケンス形式と末尾のカンマとを区別するように YAPF を設定しました。末尾のカンマが省略されると、YAPF はシーケンスを1つの行として整形します。末尾のカンマがある場合、YAPF はシーケンスを1行1項目で整形します。
170
171一般的に1行が短い定義になるようにすべきです。読みやすさと保守性を向上させるために、後からではなく早めに複数の行を分割してください。
172
173# 括弧
174
175過度な括弧は避けますが、括弧を使ってコードを理解しやすくします。タプルを明示的に返すか、あるいは数式の一部である場合を除き、return 文で括弧を使わないでください。
176
177# 書式文字列
178
179一般的に printf 形式の書式文字列を用います。例:
180
181```
182name = 'World'
183print('Hello, %s!' % (name,))
184```
185
186このスタイルはログモジュールで使われており、私たちはそれを広範囲で利用しており、一貫性を保つために他の場所でも採用しています。これは、私たちの気まぐれな読者の大部分である C プログラマにもおなじみのスタイルです。
187
188付属の CLI モジュールは、パーセント (%) 演算子を使わずにこれらを使うことをサポートしています。詳細は、`cli.echo()` と様々な `cli.log` 関数 (例えば、`cli.log.info()`) を見てください。
189
190# 内包表記とジェネレータ表記
191
192内包表記とジェネレータの自由な使用を推奨しますが、あまりに複雑にしないでください。複雑になる場合は、理解しやすい for ループで代替します。
193
194# ラムダ
195
196使っても問題ありませんが、おそらく避けるべきです。内包表記とジェネレータを使えば、ラムダの必要性は以前ほど強くありません。
197
198# 条件式
199
200変数の割り当てでは問題ありませんが、そうでなければ避けるべきです。
201
202条件式はコードに続く if 文です。例えば:
203
204```
205x = 1 if cond else 2
206```
207
208一般にこれらを関数の引数、シーケンス項目などとして使用することはお勧めできません。見落としやすくなります。
209
210# デフォルト引数
211
212推奨されていますが、値は不変オブジェクトでなければなりません。
213
214デフォルト値に引数リストを指定する場合は、その場で変更できないオブジェクトを指定するように常に注意してください。可変オブジェクトを使うと変更は呼び出しの間で持続しますが、これは通常あなたの望むものではありませんそれがあなたのやろうとしていることであっても、他の人にとっては混乱するもので理解を妨げます。
215
216悪い:
217
218```
219def my_func(foo={}):
220 pass
221```
222
223良い:
224
225```
226def my_func(foo=None):
227 if not foo:
228 foo = {}
229```
230
231# プロパティ
232
233getter および setter 関数の代わりにプロパティを常に使います。
234
235```
236class Foo(object):
237 def __init__(self):
238 self._bar = None
239
240 @property
241 def bar(self):
242 return self._bar
243
244 @bar.setter
245 def bar(self, bar):
246 self._bar = bar
247```
248
249# True/False の評価
250
251一般的に、if 文で等価性を調べるのではなく、暗黙的な True/False 評価を行うべきです。
252
253悪い:
254
255```
256if foo == True:
257 pass
258
259if bar == False:
260 pass
261```
262
263良い:
264
265```
266if foo:
267 pass
268
269if not bar:
270 pass
271```
272
273# デコレータ
274
275適切な時に使ってください。理解に役立つ時を除き、魔法の(ように見える技巧の)使いすぎは避けるようにしてください。
276
277# スレッドとマルチプロセス
278
279避けるべきです。これが必要な場合は、私たちがコードをマージする前に十分な理由を述べる必要があります。
280
281# 強力な機能
282
283Python は非常に柔軟な言語で、独自のメタクラス、バイトコードへのアクセス、実行中コンパイル、動的な継承、オブジェクトの親の変更、インポートハック、リフレクション、システム内部の変更など、多くの素晴らしい機能を提供します。
284
285これらを使わないでください。
286
287パフォーマンスは私たちにとって重要な関心ごとではなく、コードのわかりやすさに関心があります。私たちは、コードベースを1日か2日しかいじっていない人が利用できるようにしたいです。これらの機能は一般的に理解のしやすさを犠牲にするため、より高速あるいはよりコンパクトなコードよりも、容易に理解できるコードの方が望ましいです。
288
289一部の標準ライブラリモジュールはこれらの手法を使っており、これらのモジュールを利用しても問題ありません。ただし、それらを使う時には、読みやすさと理解のしやすさを忘れないでください。
290
291# 型アノテーション付きコード
292
293今のところ型アノテーションシステムを使っていないため、コードにアノテーションをつけないようにしてください。将来的にはこれを再検討する可能性があります。
294
295# 関数の長さ
296
297小さくて焦点のあった関数にしてください。
298
299長い関数が時には適切であることを理解しているので、関数の長さには厳密な制限はありません。関数が約40行を超える場合は、プログラムの構造を損なわずに分割できるかどうかを検討してください。
300
301今のところ長い関数が完全に機能するとしても、数か月でそれを変更する人が新しい挙動を追加するかもしれません。これにより見つけにくいバグが発生するかもしれません。関数を短くかつシンプルにすることで、他の人がコードを読んで修正しやすくします。
302
303幾つかのコードで作業をすると、長く複雑な関数を見つけるかもしれません。既存コードを変更することを怖がらないでください: もし、難しいことが判明したり、エラーがデバッグしづらいとわかったり、いくつかの異なるコンテキストで一部を使いたいような関数を扱っている場合、関数を小さくてより扱いやすい単位に分割することを検討してください。
304
305# FIXME
306
307FIXME をコードに残しても構いません。なぜでしょうか?このコードを文章化しないままにするよりも、少なくとも考え抜く必要がある(あるいは混乱している)コードの一部を文章化するように奨励する方が、このコードを文章化しないままにするよりも良いです。
308
309全ての FIXME は以下のように書式化されるべきです:
310
311```
312FIXME(username): 何々機能が完了したらこのコードを再検討する。
313```
314
315...username はあなたの GitHub のユーザ名です。
316
317# テスト
318
319統合テストと単体テストの組み合わせを使ってコードが可能な限りバグが無いようにします。全てのテストは `lib/python/qmk/tests/` にあります。`qmk pytest` を使って全てのテストを実行することができます。
320
321これを書いている時点では、テストは全く完全なものではありません。現在のテストを見て、テストされていない状況のための新しいテストケースを書くことは、コードベースに精通し、QMK に貢献するという両方の点で素晴らしい方法です。
322
323## 統合テスト
324
325統合テストは `lib/python/qmk/tests/test_cli_commands.py` にあります。ここで実際に CLI コマンドが実行され、全体的な動作が検証されます。[`subprocess`](https://docs.python.org/3.6/library/subprocess.html#module-subprocess) を使って各 CLI コマンドを起動し、正しく動作するかを判断するために出力とリターンコードの組み合わせを使います。
326
327## ユニットテスト
328
329`lib/python/qmk/tests/` 内の他の `test_*.py` ファイルはユニットテストを含みます。`lib/python/qmk/` 内の個々の関数のテストをここに書くことができます。一般的にこれらのファイルはモジュールに基づいて名前を付けられ、ドットはアンダースコアで置き換えられます。
330
331これを書いている時点では、テストのためのモックを作っていません。これを変更する手伝いをしたい場合は、[issue を開く](https://github.com/qmk/qmk_firmware/issues/new?assignees=&labels=cli%2C+python&template=other_issues.md&title=) か [Discord の #cli に参加](https://discord.gg/heQPAgy)し、そこで会話を開始してください。