プライベート変数
__spam 形式のマングリングが気に入らないから、
__getattribute__() や __setattr__() だのを使ってプライベート変数を実現しようと遊んでたけど。
そういえば Javascript でも似たよーなのあったなと思いだし、適当に書いてみた。
そしたら動いた。
こんなことも暫く思いつかなかったなんて……。
はふん!!
class Properties(object): """属性でアクセスできる辞書。 ただのラッパ。 >>> p = Properties(value=1) >>> p.value 1 """ def __init__(self, **kwargs): self.__dict__.update(kwargs) class Class(object): """プライベート変数を持つクラス。 >>> c1 = Class(1) >>> c1.value() 1 >>> c1.private Traceback (most recent call last): ... AttributeError: 'Class' object has no attribute 'private' >>> c1._ Traceback (most recent call last): ... AttributeError: 'Class' object has no attribute '_' >>> c1.private_method() Traceback (most recent call last): ... AttributeError: 'Class' object has no attribute 'private_method' >>> c1.proxy_private_method() 101 >>> c2 = Class(2) >>> c2.value() 2 >>> c1.increment() >>> c1.value() 2 >>> c2.value() 2 """ def closure(): """クロージャ用の仮スコープ。""" _ = {} # クロージャ経由でアクセスされる変数。 def __init__(self, value): _[self] = Properties(value=value) def __del__(self): del _[self] def value(self): return _[self].value def increment(self): _[self].value = _[self].value + 1 def proxy_private_method(self): # private_method はクラスの辞書にないので、 # _ と同じようにクロージャ経由でアクセスする。 # 当然メソッド化もされていないので、 self を渡してやる。 return private_method(self) def private_method(self): return _[self].value + 100 # 公開するものだけ出す。 _ と private_method は出さない。 return __init__, __del__, value, increment, proxy_private_method # closure() から取り出すものを取り出して __init__, __del__, value, increment, proxy_private_method = closure() # 用が終わったら削除する。 del closure
以下、未検証。ただし検証する予定もない。
private_method の扱い。
クラス (正確には type のインスタンス) の辞書に入っている関数にアクセスするとき、
__getattribute__() によって、関数 (function) はメソッド (bound method) 化されてから返される。
private_method は、そもそも type のコンストラクタに渡されていない。
よってクラスの辞書にも入らず、メソッド化もされない。
だから self を渡してやる必要がある。
まあ、 private_method に限らずとも、スコープが解決できてるなら、同じようにアクセスできるけどね……。
(__getattribute__() は属性アクセスされるときに呼ばれるだけだから)