LoginSignup
0

More than 1 year has passed since last update.

きれいに書きたいPythonプログラミング、マジックナンバーについて

Last updated at Posted at 2022-04-09

まとめ

  1. その意味や意図が記述した本人以外には自明では数値や文字列をマジックナンバーと呼ぶ。
  2. マジックナンバーは、1.から意図が読みにくいので避けるべき。
  3. 1.にもある通り数字だけでなく文字列でもマジックナンバーを避けるべき。

参考文献

1.はPythonできれいなコードを書くためのヒントをまとめた書籍となっています。2.は、マジックナンバーの辞書的な意味を調べるのに使いました。

  1. https://book.mynavi.jp/ec/products/detail/id=127578
  2. https://e-words.jp/w/%E3%83%9E%E3%82%B8%E3%83%83%E3%82%AF%E3%83%8A%E3%83%B3%E3%83%90%E3%83%BC.html

具体例:数値のマジックナンバーについて

本記事ではまず、1時間15分の試験を今から始めた場合の試験終了時刻を求めた値をtime_limitという変数に格納するような操作を考えます。

よくないと思われるマジックナンバー(数値)の例

まずは、以下によくないと思われる例を用意します。一般的にsnake_caseに則って変数名を決めるため出てくる変数time_limitもそれに則りました。そしてこの4500という値について、timeをインポートしていて変数もtime_limitなのでなんらかの期限となる時刻と関係することまでは容易に伝わると思いますが、これが1時間15分の秒数であるというのは伝わりにくいかと思います。

import time
time_limit = time.time() + 4500

マジックナンバーを排除した例

次に、マジックナンバーを排除した例を記載します。Pythonだとなるべく定数として扱いたい変数は大文字で表記することが多く、追加した変数2つはそれに則りました。SECONDS_PER_MINUTEは1分に含まれる秒数を表し、MINUTES_PER_TESTは1試験時間に含まれる分数を表しています。それらを使って変数SECONDS_PER_TESTという1試験時間に含まれる秒数を格納する変数を作りました。これで、コードからtime_limitが何を指すのかは見えやすくなったはずです。

import time
SECONDS_PER_MINUTE = 60
MINUTES_PER_TEST = 75
SECONDS_PER_TEST = SECONDS_PER_MINUTE * MINUTES_PER_TEST

time_limit = time.time() + SECONDS_PER_TEST

また、当たり前ですが別の意図によって作られた同じ値を持つ変数は分けておかなければなりません。例えば上の場合MINUTES_PER_TESTは75ですが、MINUTES_PER_TESTが60だった場合SECONDS_PER_MINUTEと同じ値だからSECONDS_PER_MINUTEMINUTES_PER_TESTのように扱うようなことは避けるべきです。

具体例:文字列のマジックナンバーについて

次に、sakana定食と'niku'定食のどちらを頼むかをinput()で受け取って、もし受け取った値がnikuの場合niku定食は売り切れとなっています。申し訳ございません。と表示するような操作を考えてみます。ここで受け取る値は、sakananikuの2つの値のみを想定しているということにします。

よくないと思われるマジックナンバー(文字列)の例

下記の場合はエラーとなりませんが、nikuと受け取ってもそれは誤字で記述されたnikiではないので何も返ってきません。変数orderと比較することはできますが、誤字によってすり抜けてしまっています。ですので、誤字をしない以外という意識以外にも用意できるなんらかの工夫をしたほうがよいと思われます。

order = input("sakana定食かniku定食を選んでください。")
if order = "niki":
  print("niku定食は売り切れとなっています。申し訳ございません。")

マジックナンバーを排除した例

次に、マジックナンバーを排除した例を記載します。NIKUという変数を用意し、比較用に準備しました。同じような誤字をしてしまっていますが、この場合すり抜けることはなくエラーが発生するのでそれに対処する形で修正できます。このような単純な例だとそこまで深刻な話でもないのですが、受け取った文字列によって何らかの特別な操作が必要な場合このような工夫をしたほうがよいと思われます。

NIKI = "niku"

order = input("sakana定食かniku定食を選んでください。")
if order = NIKI:
  print("niku定食は売り切れとなっています。申し訳ございません。")

感想

  • そこまで強く意識していなかった部分なので、気をつけていきたい。
    • リーダブルコードを積ん読にしてN年が経過しました。

次にやる、この記事に関連すること

  • 参考文献1.をもう少し読み込む
    • リーダブルコ(死後強まる念)

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
0