例えば次のクラスlog2計算機はクラス変数として底が存在する。
クラス変数を持つクラスの例
>>> import math
>>> class log2計算機:
... 底 = 2
... def __init__(self, 真数):
... self.__真数 = 真数
... def 計算(self):
... return math.log(self.__真数, log2計算機.底)
...
>>> log2計算機(8).計算()
3.0
が、外部から容易に変更可能であるため、「クラス定数」と呼ぶことができない。
変数は容易に変更可能
>>> log2計算機.底 = 4
>>> log2計算機(8).計算()
1.5 # これはlog4(8)の結果である
定数を実現する一つのアイデアとして「クラスを返すエンクロージャ」を作ってしまうというものがある。
エンクロージャ内のローカル変数は、外部から変更できない。この性質によって、「エンクロージャ内のローカル変数」を「クロージャの定数」とみることができる。
エンクロージャの変数こそ定数である
>>> def log2計算機を返すエンクロージャ():
... エンクロージャの変数としての底 = 2
... class log2計算機:
... def __init__(self, 真数):
... self.__真数 = 真数
... def 計算(self):
... return math.log(self.__真数, エンクロージャの変数としての底)
... return log2計算機
...
>>> log2計算機 = log2計算機を返すエンクロージャ()
>>> log2計算機
<class'__main__.log2計算機を返すエンクロージャ.<locals>.log2計算機'>
>>> log2計算機(8).計算()
3.0
後から、スコープ__main__.log2計算機を返すエンクロージャ.<locals>内の変数であるエンクロージャの変数としての底を書き換えることはできない。故にエンクロージャの変数としての底はクロージャlog2計算機の定数とみることができる。