python について
Python 3.11 以降のコードを作成・変更する開発者向けの規約とツール設定ガイドです。型付け、データモデル、非同期タスク、テスト、パッケージングに加え、厳格な mypy の基準を扱います。
主な機能
- 01公開関数のシグネチャに型を付与
- 02Protocol とデータクラスを優先
- 03pathlib と安全なデフォルト値を使用
- 04TaskGroup で非同期タスクを管理
- 05pytest のフィクスチャとパラメータ化を使用
- 06厳格な mypy と Ruff を設定
活用シーン
- 01新しい Python コードに一貫した規約を適用
- 02変更内容の型と非同期処理の安全性を確認
- 03パッケージング、lint、テストの慣行を整備
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ alexander-danilenko/ cortex-ai-skills --skill pythonインストール後、Claude Code で/pythonを入力して読み込まれたか確認します。
詳細
Python
Python 3.11 以降のプロジェクト内規です。新規作成または変更するコードに適用してください。依頼がない限り、変更していないファイルをこの規約に合わせてリファクタリングしないでください。
規約
-
すべての公開シグネチャに型を付け、
mypy --strictを通してください。内部の型注釈は任意です。境界部分の型注釈によって、呼び出し元から誤った値が渡されるのを防げます。 -
組み込みジェネリックと
X | Noneを使います —list[str]、dict[str, int]、str | Noneのように記述します。typing.ListとOptional[str]は 3.10 より前の表記であり、インポートが増えるだけです。 -
ABC の継承より
Protocolを優先します。 構造的部分型付けにより、テスト用の代替オブジェクトを含め、形状が正しいオブジェクトであれば、継承ツリーを維持せずに契約を満たせます。 -
データにはデータクラスを使い、適切な場合は
slots=Trueとfrozen=Trueを指定します。これらは__init__、__repr__、__eq__を正しく生成します。フィールド間の不整合は、手書きの__init__から生じ始めます。Pydantic は境界での検証や(逆)シリアライズに使い、単純なレコードには使いません。 -
os.pathではなくpathlibを使います。 演算子による結合なら、余分な区切り文字によって誤ったパスができることはありません。 -
変更可能なデフォルト引数は使いません。
def f(items=[])はすべての呼び出しで同じリストを共有します。2 回目の呼び出しで初めて現れるバグになります。デフォルト値にはNoneを指定し、関数内で作成してください。 -
単独の
gatherよりasyncio.TaskGroupを使います(3.11 以降)。失敗時に兄弟タスクをキャンセルし、ExceptionGroupで報告するため、タスクがクラッシュしても残りのタスクが切り離されたまま実行され続けることはありません。期限の設定にはasync with asyncio.timeout(n)を使います。 -
すべての
create_taskの参照を保持します。 イベントループは弱参照しか保持しないため、ファイア・アンド・フォーゲットのタスクは実行中にガベージコレクションされ、何事もなかったかのように消えてしまうことがあります。エラーも結果も残りません。setに保持し、完了時に破棄してください。_tasks: set[asyncio.Task[None]] = set() def spawn(coro: Coroutine[None, None, None]) -> None: task = asyncio.create_task(coro) _tasks.add(task) task.add_done_callback(_tasks.discard) -
単独の
except:は使いません。KeyboardInterruptとSystemExitまで握りつぶしてしまいます。実際に処理できる例外を捕捉してください。 -
公開関数とクラスには Google スタイルの docstring を付け、シグネチャを言い換えるのではなく、意図を記述してください。詳しいルールは
documentationスキルを参照してください。 -
pytest では、セットアップにフィクスチャを、ケースの指定に
parametrizeを使います。 1 つのテスト内のループでは、失敗が 1 件として報告され、どのケースで問題が起きたのか分かりにくくなります。parametrizeを使えば、ケースごとに名前が付きます。 -
パッケージ化には Poetry と
pyproject.tomlを使い、Lint とフォーマットには ruff を使います。また、型情報を利用者に公開するパッケージにはpy.typedマーカーを含めてください。src/レイアウトを使うと、インストール済みパッケージではなく作業ディレクトリからテストがインポートされるのを防げます。これにより、壊れたパッケージが自分自身のテストを通過してしまう事態を避けられます。
ツールの基本設定
strict = true で大部分をカバーできます。以下は、スタイルではなく実際のバグを検出するための追加チェックです。--strict-markers は見た目以上に重要です。これがないと、@pytest.mark.integraton のようなタイプミスが何も起こさず、除外したつもりの場所でテストが実行されてしまいます。
[tool.mypy]
strict = true
warn_unreachable = true
warn_redundant_casts = true
warn_unused_ignores = true
[[tool.mypy.overrides]]
module = "untyped_dep.*"
ignore_missing_imports = true
[tool.pytest.ini_options]
addopts = ["-ra", "--strict-markers", "--strict-config"]