1.

Python の基本ルール|インデント・PEP 8・命名規則・import の順序

編集
この記事の要点
  • Python はインデントがブロック。波かっこもセミコロンも使わない
  • インデントは半角スペース 4 個。タブとスペースを混ぜると TabError になる
  • コメントは #。関数やクラスの説明は先頭行の docstring"""...""")に書く
  • 命名は関数・変数が snake_case、クラスが PascalCase、定数が UPPER_SNAKE
  • スタイルの正解は PEP 8。迷ったら blackruff に任せて手で悩まない

ブロックはインデントで表す

多くの言語が { } で囲む範囲を、Python は行頭の空白の深さで表します。ブロックの始まりの行末には : を付けます。

def greet(name):
    if name:
        print(f"こんにちは {name} さん")
    else:
        print("名前がありません")
    return None          # ← ここは if を抜けている(インデントが浅い)

greet("田中")

同じブロック内は必ず同じ深さにそろえます。深さが合わないと実行前に IndentationError で止まります。

インデントは半角スペース 4 個

状況結果
スペース 4 個で統一PEP 8 の推奨。これにする
スペース 2 個で統一動くが Python では少数派
タブで統一動くが混在事故のもと
タブとスペースが混在TabError: inconsistent use of tabs and spaces

見た目が同じでも中身が違うため、コピー&ペーストで混ざるのがよくある原因です。エディタで「タブをスペースに変換」「空白の可視化」を有効にしておくと防げます。

文の区切りと行の継続

total = 1 + 2 + 3        # 行末にセミコロンは不要

# 長い式は「かっこの中」で改行するのが定石
total = (
    1_000_000
    + 2_000_000
    + 3_000_000
)

# リスト・辞書・引数リストも同じ。末尾のカンマを残すと差分がきれいになる
config = {
    "host": "localhost",
    "port": 8000,
}

x = 1; y = 2             # セミコロンで並べられるが PEP 8 では非推奨

行末のバックスラッシュでも継続できますが、末尾に空白が 1 個入るだけで壊れるため、かっこで囲む方法だけを使うのが安全です。

コメントと docstring

# 行コメント。コードと同じ行に書くときは 2 スペース空ける
price = 100  # 税抜き

def area(width, height):
    """長方形の面積を返す。

    Args:
        width: 幅
        height: 高さ
    Returns:
        面積
    """
    return width * height

print(area.__doc__)      # docstring は実行時に読み出せる
help(area)               # help() でも表示される

Python に複数行コメントの構文はありません。"""..."""ただの文字列リテラルで、関数・クラス・モジュールの先頭に置いたときだけ docstring として扱われます。途中に置いた三重クォートは実行時に評価される無駄な文字列なので、コメントアウトの代わりに使わないでください。

命名規則(PEP 8)

対象書き方
変数・関数・メソッドsnake_caseuser_name get_total()
クラスPascalCaseUserProfile
定数UPPER_SNAKEMAX_RETRY
モジュール・パッケージ短い小文字utils.py
内部用先頭にアンダースコア 1 個_cache
名前の衝突を避けたい属性先頭にアンダースコア 2 個__value

先頭アンダースコア 1 個は「外から触らないでほしい」という合図だけで、アクセスは制限されません。2 個の場合はクラス内で _クラス名__value に置き換えられる(名前マングリング)ため、実質的に外から触りにくくなります。

import の書き方

# 1. 標準ライブラリ
import os
import sys
from pathlib import Path

# 2. サードパーティ(pip で入れたもの)
import requests
import numpy as np

# 3. 自作モジュール
from myapp.models import User

# 1 行に複数モジュールは書かない
import os, sys        # 非推奨

# ワイルドカードは名前がどこから来たか分からなくなる
from os import *      # 使わない

import はファイルの先頭にまとめ、標準ライブラリ → サードパーティ → 自作の順に、グループごとに空行で区切ります。ruffisort が自動で並べ替えてくれます。詳しくは モジュール を参照してください。

1 行の長さとフォーマッタ

PEP 8 の上限は 79 文字ですが、実務では black の既定である 88 文字を採用するプロジェクトが多数です。重要なのは数字そのものではなくプロジェクト内で統一されていることです。

pip install black ruff

black .            # 整形(クォートはダブルに統一される)
ruff check .       # 未使用 import・未定義変数などを検出
ruff check --fix . # 直せるものは自動修正

整形ルールを人間が議論しても価値が出ません。ツールの既定値に従い、設定は pyproject.toml に 1 か所だけ書くのが省力です。

型ヒント

def total(prices: list[int], tax: float = 0.1) -> int:
    return int(sum(prices) * (1 + tax))

name: str = "田中"
count: int | None = None      # None を許す場合

型ヒントは実行時にチェックされません。間違った型を渡しても Python は動きます。検査したい場合は mypypyright を別途走らせます。エディタの補完が効くようになるので、関数の引数と戻り値だけでも付けておく価値があります。

よく出るエラーと原因

エラーよくある原因
IndentationError: expected an indented block: の次の行をインデントしていない
IndentationError: unexpected indent不要な空白が行頭にある
TabErrorタブとスペースの混在
SyntaxError: invalid syntax: の付け忘れ、かっこの閉じ忘れ(前の行を疑う)
NameErrorスペルミス、定義前の参照、import 漏れ

エラーが指す行に問題が見当たらないときは、その 1 つ前の行の閉じかっこを確認すると解決することが多いです。

1 ファイルの標準的な構成

"""売上データを集計するスクリプト。"""      # モジュールの docstring

import csv                                  # import は先頭にまとめる
from pathlib import Path

TAX_RATE = 0.1                              # 定数は大文字


def load(path: Path) -> list[dict]:
    """CSV を読み込んで辞書のリストで返す。"""
    with path.open(encoding="utf-8") as f:
        return list(csv.DictReader(f))


def total(rows: list[dict]) -> int:
    return sum(int(r["price"]) for r in rows)


def main() -> None:
    rows = load(Path("sales.csv"))
    print(f"合計 {total(rows):,} 円")


if __name__ == "__main__":
    main()

関数やクラスの定義の間は空行 2 行、メソッドの間は空行 1 行が PEP 8 の決まりです。

if __name__ == "__main__" の意味

# tool.py
print("読み込まれた")

def run():
    print("実行された")

if __name__ == "__main__":
    run()
python tool.py
# 読み込まれた
# 実行された

python -c "import tool"
# 読み込まれた        ← run() は呼ばれない

__name__ は、直接実行したときだけ "__main__" になります。この 1 行があると、ほかのファイルから import しても勝手に処理が走りません。テストや再利用のために必ず入れてください。

print と f-string

name, price = "りんご", 1280

print(f"{name} は {price} 円")        # りんご は 1280 円
print(f"{price:,}")                   # 1,280      3 桁区切り
print(f"{3.14159:.2f}")               # 3.14       小数第 2 位まで
print(f"{name=}")                     # name='りんご'   デバッグ用

print("a", "b", sep="-")              # a-b
print("進行中", end="")                # 改行しない

# 括弧を忘れると Python 3 では構文エラー
print "hello"     # SyntaxError: Missing parentheses in call to 'print'

最後の書き方は Python 2 のものです。ネット上のサンプルをそのまま試したときに出やすいエラーで、その記事全体が Python 2 向けである合図でもあります。

関連

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 基本的なルール
  2. 変数
  3. 演算子
  4. 標準ライブラリ
  5. 外部ライブラリ
  6. 制御構文
  7. リスト(配列)
  8. タプル
  9. セット
  10. 辞書(dict)
  11. クラスとメソッド
  12. 継承の概念と必要性
  13. 継承の構文
  14. コンストラクタ
  15. cookieの値の設定と取得
  16. 例外処理
  17. 例外を文字列で出力する方法
  18. httpリクエスト(curl)をする方法
  19. Responseオブジェクトの中身の確認
  20. 変数が空かどうか判定する方法
  21. タイムゾーンの設定と現在日時の取得と文字列化
  22. シングルクォーテーションとダブルクォーテーションの違い

最近更新/作成されたページ