Python基礎・実行環境と「定数」のイメージをそろえる
Pythonを学び始めると、「変数」はすぐにイメージできますが、「定数」は少しわかりにくい概念かもしれません。 特にPythonには、CやJavaのような「絶対に書き換えられない定数」を作るための専用キーワードがありません。その代わりに、「これは変えない値ですよ」という“約束”をコードで表現するスタイルが使われています。
ここでは、初心者向けに「定数とは何か」「Pythonではどう定義するのか」「どう書くと安全で読みやすいのか」を、例題やテンプレートを交えながら丁寧に解説していきます。
定数とは何か(Pythonにおける定数の考え方)
定数の役割
定数とは、プログラムの実行中に変わらない値に名前をつけたものです。
- 数学的な値:
PI = 3.1415926535 - 設定値:
MAX_RETRIES = 3、DEFAULT_TIMEOUT = 30 - ドメイン固有の値:
TAX_RATE = 0.1、DISCOUNT_RATE = 0.2
こうした値は、コードのあちこちに「生の数字(マジックナンバー)」として書いてしまうと意味がわかりにくくなり、変更も大変になります。 そこで、「名前付きの定数」としてまとめておくことで、意図が伝わりやすくなり、変更も1か所で済むようになります。
Pythonには「本物の定数」がない
Pythonには const のようなキーワードがなく、技術的にはどんな変数も再代入できます。
PI = 3.1415926535
PI = 3 # 技術的には書き換え可能
PythonそれでもPythonコミュニティでは、
- 「大文字+アンダースコア」で書かれた名前は定数として扱う
- それを勝手に書き換えるのは“やってはいけないこと”
という強い慣習(社会的なルール)が共有されています。
Pythonで定数を定義する基本スタイル(最重要)
UPPER_SNAKE_CASE(全部大文字+アンダースコア)
Pythonの公式スタイルガイド(PEP 8)では、定数はモジュールの先頭で「全部大文字+アンダースコア」で書くことが推奨されています。
# 定数の定義例(モジュールの先頭)
PI = 3.1415926535
MAX_RETRIES = 3
DEFAULT_TIMEOUT = 30 # 秒
TAX_RATE = 0.1 # 消費税率
PythonPIやMAX_RETRIESのような「叫んでいるような名前(SCREAMING_SNAKE_CASE)」は、「これは変えない値ですよ」というサインになります。
モジュールの先頭にまとめる
定数は、そのファイル(モジュール)の先頭付近にまとめて書くのが一般的です。
import math
# ここから定数定義
PI = 3.1415926535
MAX_CONNECTIONS = 100
DEFAULT_TIMEOUT = 30
# ここから関数定義
def calculate_circle_area(radius):
return PI * radius * radius
Pythonこうしておくと、
- 「このファイルで使われる固定値」が一目でわかる
- 設定値を変えたいときに、先頭だけ見ればよい
というメリットがあります。
定数を使うメリットを具体例で見る
マジックナンバーを定数に置き換える
悪い例(マジックナンバーだらけ):
def compute_net_salary(hours):
return hours * 35 * (1 - (0.04 + 0.10))
Python35が何の数字なのか0.04と0.10が何を意味するのか
コードを読んだ人が「推測」しないといけません。
良い例(定数を使う):
HOURLY_SALARY = 35
SOCIAL_SECURITY_TAX_RATE = 0.04
FEDERAL_TAX_RATE = 0.10
def compute_net_salary(hours):
return hours * HOURLY_SALARY * (1 - (SOCIAL_SECURITY_TAX_RATE + FEDERAL_TAX_RATE))
Python- 「時給」「社会保障税率」「連邦税率」という意味が名前から伝わります。
- 税率が変わったときは、定数の定義だけ変えれば済みます。
このように、定数はコードの意味を明確にし、変更に強くするための道具です。
実務でよく使う定数のパターン
設定値・しきい値
MAX_LOGIN_ATTEMPTS = 5
DEFAULT_PAGE_SIZE = 20
API_TIMEOUT_SECONDS = 30
Python- セキュリティ的に重要なしきい値(ログイン試行回数など)は、必ず定数としてまとめておくと安全です。
URLやパス
API_BASE_URL = "https://api.example.com/v1"
LOG_FILE_PATH = "/var/log/myapp.log"
Python- 文字列をあちこちにベタ書きせず、定数にしておくことで変更漏れを防ぎます。
サポートするフォーマットなどの「閉じた集合」
SUPPORTED_FORMATS = ("png", "jpg", "webp") # タプルにして不変にする
Python- リストではなくタプルにすることで、「基本的に変えない集合」であることをより強く表現できます。
「定数を守る」ための補助テクニック(少しステップアップ)
typing.Final を使って「変えない意図」をツールに伝える
Python 3.8以降では、typing.Final を使うことで、静的型チェッカー(mypyなど)に「この名前は再代入してはいけない」と伝えることができます。
from typing import Final
MAX_CONNECTIONS: Final = 100
API_VERSION: Final[str] = "v2"
Python- 実行時には普通の変数と同じように振る舞います(Python自体は止めません)。
- しかし、
MAX_CONNECTIONS = 200のような再代入をすると、mypyなどが「定数を変えていますよ」と警告してくれます。
初心者のうちは必須ではありませんが、「定数をちゃんと守りたい」と思ったときに使える選択肢として覚えておくとよいです。
クラス内での定数定義
定数が特定のクラスにだけ関係する場合、クラス属性として定義することもあります。
class RateLimiter:
MAX_REQUESTS = 60
COOLDOWN_SECONDS = 5
def __init__(self):
self.count = 0
Python- クラスの先頭に大文字の名前で書くことで、「このクラス専用の定数」であることがわかります。
- それでも「書き換えない」という約束は同じです。
定数定義のテンプレート(そのまま使える形)
モジュール先頭の定数ブロック
# ==============================
# 定数定義
# ==============================
PI = 3.1415926535
MAX_RETRIES = 3
DEFAULT_TIMEOUT = 30 # 秒
API_BASE_URL = "https://api.example.com/v1"
SUPPORTED_FORMATS = ("png", "jpg", "webp")
Pythonセキュリティ関連の定数
# 【SECURITY】ログイン試行回数の上限
MAX_LOGIN_ATTEMPTS = 5
# 【SECURITY】アカウントロックまでの待機秒数
ACCOUNT_LOCK_SECONDS = 300
Python- セキュリティ上重要な値には、コメントで「これは安全性に関わる値だ」と明示しておくと、後から変更するときに慎重になれます。
練習問題:定数を使ってコードを整理する
元のコード
def calculate_final_price(price):
return price * (1 - 0.2) * (1 + 0.1)
Python定数を使った改善例
# 割引率(キャンペーン期間中は20%)
DISCOUNT_RATE = 0.2
# 税率(日本の標準消費税)
TAX_RATE = 0.1
def calculate_final_price(price):
return price * (1 - DISCOUNT_RATE) * (1 + TAX_RATE)
Python- 「0.2」「0.1」が何を意味するのか、名前からすぐにわかります。
- キャンペーン内容や税率が変わったときも、定数定義だけ変えれば済みます。
まとめ
- Pythonには「絶対に変えられない定数」を作るキーワードはありません。
- その代わりに、全部大文字+アンダースコア(UPPER_SNAKE_CASE)で名前を付け、モジュール先頭にまとめて定義するという強い慣習があります。
- 定数を使うことで、マジックナンバーをなくし、コードの意味を明確にし、変更に強い設計にできます。
- セキュリティ上重要なしきい値や設定値は、必ず定数として切り出し、コメントで意図を残すと安全性が高まります。
初心者のうちは、「変わらない値は必ず定数にする」「定数名は大文字で意味が伝わるようにする」という2つの習慣を意識するだけで、コードの質が大きく変わっていきます。
