IT・技術研修ならCTC教育サービス

サイト内検索 企業情報 サイトマップ

研修コース検索

コラム

ゼロから歩くPythonの道

CTC 教育サービス

 [IT研修]注目キーワード   Python  Power Platform  最新技術動向  生成AI  Docker  Kubernetes 

第62回 Pythonプログラムでエラーを出す前に確認したいこと ~マジックナンバー編~ (菱沼佑香) 2025年3月

こんにちは、吉政創成 菱沼です。
今回も「きれいなPythonプログラミング(マイナビ出版)」という書籍を利用して学習します。

現在は5章「怪しいコード臭」です。バグを未然に防ぐために、どういった点に注意した方が良いのか、対処するか否かの判断について学んでいます。今回はマジックナンバーについてです。

その人にしかわからないマジックナンバーをどうにかする

さて、げんなりするエラーメッセージが起きないように事前にどのポイントを見ればいいのか学ぶこの章。
今回はマジックナンバーという項目です。
そもそもマジックナンバーとはなんぞ。

コンピュータプログラムのソースコードなどに直に記述された数値で、その意味や意図が記述した本人以外には自明ではないもの。そのような値などをコード中に直に書いてしまうことを「ハードコード」という。
by IT用語辞典:マジックナンバー

数字をそのまま書いたもの、かつ、本人以外にはその数字の意味や意図が分からないもののことを指すということですが、ではそうしたマジックナンバーをどのように扱っていけばいいのかという点です。

---------------------------------------------------------------
P.75、76
ソースコードに登場する数字の中には、他のプログラマー(あるいは数週間後のあなた)を混乱させるものがあります。例えば、次のコードの604800という数字を考えてみましょう。


expiration = time.time() + 604800

time.time()関数は、現在の時刻を表す整数を返します。このexpiration(有効期限)という変数は、604800秒先のある時点を表すと考えられます。しかし、604800という数字はよくわかりませんね。個の有効期限にはどんな意味があるのでしょうか?コメントがあれば、それがはっきりわかります。


expiration = time.time() + 604800  # 1週間で期限切れになる

これでわかりやすくなりましたが、もっとよいのはこれらのマジックナンバーを定数に置き換えることです。
---------------------------------------------------------------

確かにコメントで書いておくというのもわかりやすくするポイントですね。
ただ、マジックナンバーを定数に置き換える方がより良いという事なんですが、定数と言えば、あれです。命名規則のときにでてきましたね。変数名をすべて大文字で書き(例:SNAKE_CASE)、最初に入れられた値が変化しないあれです。

通常、定数はソースコードファイルの先頭にグローバル変数として定義されるそうです。その時の書き方の例がこちら。

#  さまざまな時間単位を秒で表す
SECONDS_PER_MINUTE = 60
SECONDS_PER_HOUR   = 60 * SECONDS_PER_MINUTE
...略
SECONDS_PER_WEEK    = 7 * SECONDS_PER_DAY

こういった内容を先に書いておけば、先ほどのコードをこのように書くことができるようになるとのこと。


expiration = time.time() + SECONDS_PER_WEEK  # 1週間で期限切れになる

数字で書かれるよりわかりやすいですね。
ちなみに同じ数字を他でも使いたい場合であっても、目的が違うのであれば、定数を使いまわすのではなく、別の箱として定数を用意した方が良いそうです。そうしておけば、先々にあの定数の数値違うものにしたいなーと思ったときに、それだけを修正すればよくなりますので、変更が容易になります。

文字列のマジックナンバーをなんとかする

さて、マジックナンバーは数字だけが対象ではないそうで、文字列なども対象となるのだそう。
というわけで、次は文字列なマジックナンバーを何とかする方法です。

---------------------------------------------------------------
P.77
このプログラムでは、ユーザーに方向を入力してもらい、その方向が北(north)の場合は警告を表示します。しかしコードの中に、例えば"nrth"のようなタイプミスがあると、プログラムが警告を表示できないというバグが発生します。


while True:
    print('Set solar panel direction:')
    direction = input().lower()
    if direction in ('north', 'south', 'east', 'west'):
        break

print('Solar panel heading set to:', direction) if direction == 'nrth': print('Warning: Facing north is inefficient for this panel.')

---------------------------------------------------------------

下から2行目の「'nrth'」は本来なら「north」と書かれるはずでしたが、文字列であるため、バグとしてエラーメッセージは表示されません。見落としたままプログラムが進むことになります。
そこで、定数として定義して先に定義しておけば、タイプミスをしたときに「NameError」のエラーメッセージが表示されるようになるため、バグに気づくことができるようになる、ということだそうです。
定数例:


NORTH = 'north'
SOUTH = 'south'

上記の定数を設定した後、該当箇所は以下のように変更されます。


変更前)if direction == 'north':
変更後)if direction == NORTH

というわけで、作った人(や、当時)にしか分からなくなる可能性の高いマジックナンバーとなる値は、数字でも文字列でも、定数として、先に宣言しておくことが解決策という事でした。これはバグ対策だけでなく、将来的にプログラムの変更が必要になったときのメンテナンスもしやすくなります。

それでは今回はこちらで終了です。今回もお付き合いいただきありがとうございました。

 

 [IT研修]注目キーワード   Python  Power Platform  最新技術動向  生成AI  Docker  Kubernetes