1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PEP:8 "Pythonコードのスタイルガイド"

1
Posted at

PEP 8とは(概要)

PEP 8 は、Pythonコードを書くときの公式スタイルガイドです。
主に「Python標準ライブラリで使うコーディング規約」として定義されていますが、一般的なPythonプロジェクトでも広く参照されています。

PEP 8で特に重要なのが、Guido van Rossumの次の考え方です。

コードは、書かれる時間よりも読まれる時間の方がはるかに長い。

つまり、コードを書くときは「自分が今わかるか」だけでなく、あとから読む人が理解しやすいか保守しやすいか を重視する必要があります。

一貫性にこだわりすぎるのは、狭い心の現れである

ただし、PEP 8は絶対的なルールではありません。
PEP 8自身も、次のような考え方を示しています。

  • プロジェクト内の一貫性を優先する
  • 可読性を下げるくらいなら、規約から外れてもよい
  • 既存コードのスタイルに合わせることも重要

つまり、PEP 8は「守るための規則」というより、読みやすく、保守しやすいPythonコードを書くための共通基準です。


PEP 8で定義されている内容

PEP 8では、主に以下のような内容が定義されています。

分類 内容
コードのレイアウトに関するルール インデント、空行、行の長さ、import文、式や文の空白など
コメントに関するルール ブロックコメント、インラインコメント、ドックストリングスなど
命名規約に関するルール モジュール名、クラス名、関数名、変数名、定数名、非公開メンバーなど
プログラミング上の推奨事項 比較、例外、関数アノテーション、変数アノテーションなど

この記事では、特に以下の3つに絞ってまとめます。

  • コードのレイアウト
  • コメント
  • 命名規約

コードのレイアウト

インデント

PEP 8では、インデントは半角スペース4つ が基本です。

def greet(name):
    print(f"Hello, {name}")

Pythonでは、インデントが構文上の意味を持ちます。
そのため、インデントの揺れは単なる見た目の問題ではなく、コードの意味そのものに影響します。

スペースとタブ

PEP 8では、タブよりもスペースが推奨されています。

# 良い例
def sample():
    print("Hello")

タブは、既存コードとの一貫性を保つ場合に限って使う扱いです。
また、Pythonではインデントにタブとスペースを混在させることはできません。

1行の長さ

PEP 8では、すべての行の長さを 79文字 までに制限するように記載されています。
また、docstringやコメントについては、72文字 までに制限するようにすべきとあります。

これは、2つのファイルを並べて開いたときに、コードを折り返さずに閲覧することができるよにするための規約です。

また、プロジェクトチームとの合意のもと、1行を 99文字 まで制限を緩めることが許容されています。

複数行にまたがる場合

長い式を書く場合は、括弧 ()、角括弧 []、波括弧 {} を使った暗黙の行継続が推奨されています。

total = (
    price
    + tax
    + shipping_fee
)

バックスラッシュ \ による行継続も使えますが、基本的には括弧を使う方が読みやすいです。

# あまり推奨されない例
total = price + \
    tax + \
    shipping_fee

空行

空行は、コードの論理的なまとまりを示すために使います。
文章でいう「段落」のようなものです。

PEP 8では、主に以下のような空行ルールがあります。

場所 空行の目安
トップレベルの関数・クラス定義の前後 2行
クラス内のメソッド定義の前後 1行
関数内の論理的な区切り 必要に応じて少なめに使用

トップレベルの関数・クラス

トップレベルの関数やクラスは、2行空けます。

class User:
    pass


def create_user():
    pass

クラス内のメソッド

クラス内のメソッド同士は、1行空けます。

class User:
    def __init__(self, name):
        self.name = name

    def greet(self):
        print(f"Hello, {self.name}")

関数内の空行

関数内では、処理のまとまりを分けたいときに空行を使います。

def process_user(user):
    name = normalize_name(user.name)
    email = normalize_email(user.email)

    if not email:
        raise ValueError("email is required")

    save_user(name, email)

空行を入れすぎると、かえって読みにくくなります。
「処理のまとまりを分けるために使う」と考えるのがよいです。


Import文

import文は、基本的にファイルの先頭にまとめて書きます。
また、通常は 1行に1つずつ 書きます。

# 良い例
import os
import sys
# 避ける例
import os, sys

ただし、from ... import ... で複数の名前を読み込む形は許容されます。

from subprocess import PIPE, Popen

import文の順序

import文は、次の順序でグループ化します。
グループ間には空行を入れます。

# 標準ライブラリ
import os
import sys

# サードパーティライブラリ
import pandas as pd
import requests

# 自作モジュール
from my_app.config import settings
from my_app.utils import normalize_text

基本的な順序は以下です。

  1. 標準ライブラリ
  2. サードパーティライブラリ
  3. 自作アプリケーション・自作ライブラリ

ワイルドカードimportは避ける

from module import * のようなワイルドカードimportは、原則として避けます。

# 避ける例
from math import *

この書き方は、どの名前が現在の名前空間に追加されたのか分かりにくくなります。
その結果、コードの可読性や保守性が下がります。


空白文字

空白文字は、可読性を高めるために使います。
ただし、余計な空白は避けます。

括弧の内側に余計な空白を入れない

# 良い例
spam(ham[1], {eggs: 2})
# 避ける例
spam( ham[ 1 ], { eggs: 2 } )

カンマ・セミコロン・コロンの直前に空白を入れない

# 良い例
print(x, y)
# 避ける例
print(x , y)

関数名と括弧の間に空白を入れない

# 良い例
print("hello")
# 避ける例
print ("hello")

代入演算子の周りには空白を入れる

# 良い例
count = 1
total = count + 10
# 避ける例
count=1
total=count+10

キーワード引数やデフォルト引数の = には空白を入れない

# 良い例
def connect(host, port=8080):
    pass

connect(host="localhost", port=8080)
# 避ける例
def connect(host, port = 8080):
    pass

connect(host = "localhost", port = 8080)

型アノテーションとデフォルト値を組み合わせる場合

型アノテーションとデフォルト値を組み合わせる場合は、= の前後に空白を入れます。

def greet(name: str = "Guest") -> None:
    print(name)

コメント

PEP 8では、コメントについて次のような考え方が示されています。

コードと矛盾するコメントは、コメントしないことよりタチが悪いです

コードを変更したら、コメントも更新する必要があります。
古いコメントが残っていると、読み手はコードとコメントのどちらを信じればよいか分からなくなります。

コメントは、コードをそのまま説明するためではなく、主に以下を補足するために使います。

  • なぜその処理をしているのか
  • 背景事情は何か
  • 注意すべき制約は何か
  • 一見すると不自然な実装にした理由は何か

ブロックコメント

ブロックコメントは、対象となるコードの直前に書きます。
インデントは、そのコードと同じレベルに合わせます。
各行は # と半角スペース1つで始めます。

# ユーザー名が未入力の場合は、仮の名前を設定する。
# 外部API側で空文字がエラーになるため。
if not user_name:
    user_name = "Guest"

複数段落に分けたい場合は、# だけの行で区切ります。

# ここでは住所文字列を正規化する。
#
# ハイフンや全角数字の揺れを吸収してから、
# 後続の住所比較処理に渡す。
normalized_address = normalize_address(address)

インラインコメント

インラインコメントは、コードと同じ行に書くコメントです。
PEP 8では、インラインコメントは控えめに使うべきとされています。

インラインコメントを書く場合は、文とコメントの間を少なくとも半角スペース2つ空け、# の後ろには半角スペースを1つ入れます。

x = x + 1  # 境界補正のため1加算する

次のように、コードを見れば分かることをコメントに書くのは避けます。

x = x + 1  # xに1を足す

これは、コメントが新しい情報を増やしていないためです。
コメントを書くなら、「何をしているか」よりも「なぜそうしているか」を書く方が有用です。


ドックストリングス

ドックストリングスは、モジュール・関数・クラス・メソッドの説明を書くための文字列です。
PEP 8では、ドックストリングスの詳細な規約は PEP 257 にまとめられています。

ドックストリングスは、対象オブジェクトの最初の文として書かれる文字列です。

def add(a: int, b: int) -> int:
    """Return the sum of a and b."""
    return a + b

複数行のドックストリングスでは、概要行、空行、詳細説明の順に書きます。
終了側の """ は独立した行に置きます。

def calculate_total(price: int, tax_rate: float) -> int:
    """Calculate the total price including tax.

    Args:
        price: Base price.
        tax_rate: Tax rate.

    Returns:
        Total price including tax.
    """
    return int(price * (1 + tax_rate))

ドックストリングスには、三重のダブルクォート """ を使うことが推奨されています。


命名規約

PEP 8では、Pythonの命名規約について以下のような基準が示されています。
既存ライブラリには歴史的な揺れがありますが、新しく書くコードでは現在の推奨規約に従うのが基本です。

対象 命名スタイル
モジュール名 小文字、必要に応じて _ user_service.py
パッケージ名 小文字、短め utils
クラス名 CapWords / PascalCase UserService
例外クラス名 CapWords、エラーなら Error 接尾辞 ValidationError
関数名 小文字 + _ calculate_total()
変数名 小文字 + _ user_name
メソッド名 小文字 + _ get_user_name()
定数名 大文字 + _ MAX_RETRY_COUNT
インスタンスメソッド第1引数 self def method(self):
クラスメソッド第1引数 cls def method(cls):
非公開メンバー 先頭に _ _internal_value
キーワード衝突回避 末尾に _ class_

例です。

MAX_RETRY_COUNT = 3


class UserService:
    def get_user_name(self, user_id: int) -> str:
        user_name = "Shoji"
        return user_name

避けた方がよい名前

lOI を1文字の変数名として使うことは避けます。
フォントによって、数字の 10 と見分けにくいためです。

非公開メンバー

Pythonには、JavaやC#のような厳密なprivateはありません。
ただし、先頭にアンダースコアを付けることで「内部利用の意図」を示します。

_internal_cache = {}

これは「外部から直接使わないでほしい」という慣習的なサインです。


静的解析ツール

PEP 8はコーディング規約なので、人間が毎回すべてを目視で確認するのは大変です。
実務では、静的解析ツールやフォーマッタを使って自動チェックするのが一般的です。

現在、多くのツールが Ruff に統合されています。ツールを個別に導入する手間や、実行速度の遅さに悩まされることがなくなります。

PEP 8 スタイルチェック・修正ツール一覧

ツール名 分類 主な役割・特徴
Ruff リンター / フォーマッタ 現在の主流。 Rust製で圧倒的に高速。
Flake8 リンター 従来の定番。
pycodestyle リンター PEP 8チェックの元祖。 (旧名 pep8)。
Pylint 総合静的解析 最も厳格。コードの品質を10点満点でスコア化する。
Black フォーマッタ 自動整形の標準。「強制的に自動修正」する。
isort フォーマッタ import文の専門家。 import文を自動で並び替える。
pydocstyle リンター docstringの専門家。
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?