Pythonでconst的なことができるライブラリを作ってみました。

皆さんご存知の通り、Pythonにはconst的な定数定義方法が存在しません。
何年かPythonを書いていたら、特に気にならずに自然に感じるようになっていたのですが、ふと使いわけでconst的な書き方ができてもいいんじゃないかと思い勢いに任せてライブラリにしてみました。[[github](https://github.com/simon-ritchie/pconst)]

# インストール方法

pipでインストールできるようにしておきました。pyconstという名前にしたかったのですが、既に別のライブラリが登録されていたので、pconstという名前にしました。

```
$ pip install pconst
```

Python2.7とPython3.6、ローカルのWin10とクラウドのUbuntuで試しているので、おそらく2系と3系両方で動きます（多分）。

※各所の英語は<font color="#aaaaaa">
Google翻訳先生に頼りっきりなので、
</font>明らかに間違っていてミスリーディングなところがありましたら弱めにマサカリ投げていただけますと幸いです。

# つかいかた

constモジュールをimportして、そちらにプロパティとして設定するだけです。

```py
from pconst import const
const.APPLE_PRICE = 100
```

アクセスは普通にできます。

```py
print(const.APPLE_PRICE)
```

```
100
```

値を変更しようとすると怒られます。

```py
const.APPLE_PRICE = 200
```

```
Constant value of "APPLE_PRICE" is not editable.
```

削除しようとしても怒られます。

```py
del const.APPLE_NAME
```

```
ConstantError: Constant values are not deletable.
```

dictやらlistも放り込めます。値に辞書を持っていて階層が深くなっている際には再帰的に定数化がされます。
listの方はtuple使えばいいんじゃ・・という気もしましたが、Pandasやjsonなどのモジュールを経由した際にいちいちtupleに変換しなくてもいいように、一応対応してあります。

```py
const.APPLE_DATA = {
    'prince': 100,
    'name': 'apple',
    'sales_list': [12300, 25000, 8200]}
print('price:', const.APPLE_DATA['price'])
print('name:', const.APPLE_DATA['name'])
print('sales_list:', const.APPLE_DATA['sales_list'])
```

```
price: 100
name: apple
sales_list: [12300, 25000, 8200]
```

※土日で終わらなくなりそうな気配がしていたので、defaultdictなどのdictやlistの亜種たちは今回は対応を見送ってあります。結構問題になりそうでしたら、将来のアップデートで対応します。

設定した辞書やリストの値を更新しようとしても、同様に怒られます。

```py
const.APPLE_DATA['price'] = 200
```

```
ConstantError: Update dict value is not allowed.
```

データの更新が走らない、dictやlistの関数はそのまま使えます。

```py
print(len(const.APPLE_DATA['sales_list']))
```

```
3
```

```py
print(const.APPLE_DATA.keys())
```

```
dict_keys(['price', 'name', 'sales_list'])
```

逆に、更新がかかる関数を実行しようとすると怒られます。

```py
const.APPLE_DATA.update({'season': 'winter'})
```

```
ConstantError: To update dict values is not allowed.
```

# 以下おまけ（余談）

## 作った動機

きっかけは、先週末に新しくPythonを書き始めた同僚の方に「Pythonでconst的な書き方をうまいことする方法はないか」と聞かれ、その時は多分無さそう・・と返答しました。
家に帰って少し調べてみても、どうやらライブラリも世の中になさそうです。

Pythonを書き始めた際には確かに少し気になりましたが、普段探索的な分析作業を行ったりする際には、定数の値も色々調整したりして実験を何度もしたりするので、特に気にならなくなっています（
慣れって怖い
）。
varもconstも{}の括弧も書かないシンプルさがPythonっぽい感じですし、世の中の他の方もまあ別になくても何とかなるよね、という意見を持っていらっしゃる印象です。（同僚のPython長いこと書いているデータサイエンティストの方も特に気になっていないとおっしゃっていました）

> 自分が知るかぎりでは汎用的にオブジェクトの再代入を禁止できる方法は聞いた事無いです. また, それを不自由だとも思いません.
> むしろこう考えると良いと思います. なぜpythonには標準でconstが無いのか. もっというとJavaなどにあるprivate, protected修飾子が無いのか.
言語仕様として静的型付け言語にあるような表現を備えず, コード規約や文化によって構造を表現することがスクリプト言語に更なる柔軟性を与えていると思います.
> [Pythonでconstant](https://qiita.com/natsutan/items/90a2d1a005cfe9afe017)

ただし、以下のstackoverflowのvoteの数などをみても、とてもconstの有無は皆さん気になるようです。（特に、長いこと他の言語を触っていた方で、新しくPythonを触り始めた方）

<img width="573" alt="20181028.png" src="https://qiita-image-store.s3.amazonaws.com/0/228778/96fab6d1-aa3e-bbbe-db6d-75cd5e772d73.png">

[How do I create a constant in Python?](https://stackoverflow.com/q/2682745)

一晩寝たら、柔軟に操作できる既存のものに加えて、固く縛って定数を扱うのも、ケースバイケースで使い分ける選択肢があってもいいのでは、と思ったのが作成の動機です（Jupyterで色々実験するのは柔軟にしつつ、FlaskやDjangoなどでもweb開発であればconst的に扱ってもいいんじゃないかなと）。

## もし動かなかったら・・

「〇〇の条件・環境で動かないよ！」「××のところ直すともっと便利」といったところがありましたら、コメントなりgithubのissueなどでご連絡ください:star2:

## PyPI登録、思ったより簡単だった

今回初めてpipでインストールできる形でライブラリを書いたので、PyPI登録も初めてでしたが、思ったよりもシンプルでした。（何となくハードルが高いイメージを持っていました）

参考にさせていただきました。:bow:

- [Pythonで作成したライブラリを、PyPIに公開/アップロードする](https://qiita.com/icoxfog417/items/edba14600323df6bf5e0)
- [PyPIデビューしたい人の為のPyPI登録の手順](https://qiita.com/kinpira/items/0a4e7c78fc5dd28bd695)