はじめに
タイトルの通りPythonで名前付きの定数値を作成する方法について記載します。
私のメイン言語はCなのですがCで言うところの#defineやconstのようなものを作ることを目指します。あくまで**"ような"**ですので名前がついていてイミュータブルな(値が変更できない)ものぐらいに捉えてください。
環境
以下の環境で動作させています。namedtuple
というデータ型が使えるPythonバージョンであればOS依存なく使えるものと思われます。
- OS
- Windows 10 64bit
- Pythonバージョン
- 3.6.6
作成例
Cで
# define D_VERSION 0.01
# define D_TITLE "sample"
のようなdefine値があったときPythonでは
from collections import namedtuple
D = namedtuple("Def", "VERSION TITLE")(
VERSION = 0.01,
TITLE = "sample"
)
# 使用例
print(D.VERSION)
print(D.TITLE)
と書くことにより実現できます。
細かい話
namedtupleとは
オフィシャルドキュメントには
名前付きフィールドを持つタプルのサブクラスを作成するファクトリ関数
と定義されています。
タプル
とはオフィシャルドキュメントには
イミュータブルなシーケンスで、一般的に異種のデータの集まりを格納するために使われる
と書かれています。つまり定数の集合体です。これに名前がついたものがnamedtuple
となります。
namedtupleの一般的な記述方法と今回の記述方法について
先程の例を一般的なnamedtupleの記述方法で記述すると以下のようになります(import等は割愛しています)。
Def = namedtuple("Def", "VERSION TITLE")
D = Def(0.01, "sample")
せっかくのnamedtupleですのでよりわかりやすく書くと
Def = namedtuple("Def", "VERSION TITLE")
D = Def(VERSION=0.01, TITLE="sample")
となります。
前述の通りnamedtupleはサブクラスを作成しますので上記コードではDef
というサブクラスが作成されることになります。
しかし今回の例では作成されたサブクラスを使い回す必要がなかったため(ユニークな名前付きの定数値を作りたいだけなので)サブクラスの宣言部分を取っ払い
D = namedtuple("Def", "VERSION TITLE")(
VERSION = 0.01,
TITLE = "sample"
)
としてしまった次第です。
個人的な話
Pythonで定数を扱いたい
私がPythonを使い始めたときに「Pythonで定数ってどうやって書くのかな?」と思い調べたところ殆どのサイトに
Pythonに定数はありません。大文字アルファベットとアンダースコアの組合せで(変数を)記載するのが慣例です
と書かれていました。PEP 8(Pythonのコードスタイルガイドライン)にそう書かれているのでそうなのですが。「見た目だけで実態は変数だから凡ミス防げないよね」というのが正直な感想でした。
その後tupleを覚えたのですが
D = (0.01, "sample")
print(D[0])
print(D[1])
これでは可読性が悪すぎる。
しばらく慣例通り大文字変数を使っていました。
その後諦めきれずに色々調べたところnamedtupleに出会った次第です。
おわりに
PythonでもCの#defineっぽいものを使いたいという衝動からnamedtupleを使ってみました。Pythonの慣例からすると間違っているのかもしれません。完全にCプログラマーの自己満足です。
ただnamedtupleを使うと
- イミュータブルになるので安全
- ドット記法が使えるので辞書型より見やすい
等の利点があると思うので今後も(別の目的で)積極的に使っていきたいと思います。ただしパフォーマンスは悪いようなので多用は禁物かもしれません。
参考
本記事を書くにあたり以下のサイトを参考・引用しました。