Python のお勉強9 ( プライベートメンバの定義 )
「Python のお勉強シリーズ」第9回目は、プライベートメンバの定義についてサンプルコード書いてみました。
■ privateMember.py
#coding: cp932 class Test: def __init__(self): self.__member = "private member" #private なメンバに値を代入 #private なメソッドを定義 def __privateMethod(self): print(self.__member) def method(self): self.__privateMethod() if __name__ == "__main__": instance = Test() print("----- call method() -----") instance.method() print("----- access private member -----") #private なメンバにはアクセスできず "AttributeError: 'Test' object has no attribute '__member'" となる (*1) instance.__member print("----- call private method -----") #private なメソッドは実行できず "AttributeError: 'Test' object has no attribute '__method'" となる (*2) instance.__method()
■ 実行結果
----- call method() ----- private member ----- access private member ----- Traceback (most recent call last): File "privateMember.py", line 22, in <module> instance.__member AttributeError: 'Test' object has no attribute '__member'
※ (*1) でエラーになるので (*2) まで行き着きませんが・・・
Python には言語としてプライベートなメンバってものは厳密にはないみたいですが、2つ以上の下線 "_" で始まる、かつ、末尾の下線が1つ以下の属性 / メソッドについては内部的に識別子が _<クラス名>__<メンバ名> という形に変換されるとのこと。これにより定義した通りの名前では属性アクセス、メソッド呼び出しができないことになります ( _<クラス名>__<メンバ名> とすれば普通にアクセス、呼び出し可能ですが )。
・9. クラス — Python 3.4.3 ドキュメント
- 9.6. プライベート変数
http://docs.python.jp/3.4/tutorial/classes.html#tut-private
上記の通り、_<クラス名>__<メンバ名> に変換されているだけなので、今回のサンプルコードだと _Test__member、_Test__privateMethod とすると普通に属性アクセス、メソッド呼び出しが可能です。
■ privateMember2.py
#coding: cp932 import inspect class Test: def __init__(self): self.__member = "private member" #private なメンバに値を代入 #private なメソッドを定義 def __privateMethod(self): print(self.__member) def method(self): self.__privateMethod() if __name__ == "__main__": instance = Test() print("----- call method() -----") instance.method() print("----- access private member -----") print(instance._Test__member) print("----- call private method -----") instance._Test__privateMethod() print("----- get instance member -----") print(inspect.getmembers(instance)) #インスタンスの全メンバを取得する _Test__member, _Test__privateMethod が存在することが確認できる
■ 実行結果
----- call method() ----- private member ----- access private member ----- private member ----- call private method ----- private member ----- get instance member ----- [('_Test__member', 'private member'), ('_Test__privateMethod', <bound method Test.__privateMe <__main__.Test object at 0x01E55750>>), ('__class__', <class '__main__.Test'>), ('__delattr_ thod-wrapper '__delattr__' of Test object at 0x01E55750>), ('__dict__', {'_Test__member': 'pr ember'}), ('__dir__', <built-in method __dir__ of Test object at 0x01E55750>), ('__doc__', No __eq__', <method-wrapper '__eq__' of Test object at 0x01E55750>), ('__format__', <built-in me format__ of Test object at 0x01E55750>), ('__ge__', <method-wrapper '__ge__' of Test object a 55750>), ('__getattribute__', <method-wrapper '__getattribute__' of Test object at 0x01E55750 _gt__', <method-wrapper '__gt__' of Test object at 0x01E55750>), ('__hash__', <method-wrapper h__' of Test object at 0x01E55750>), ('__init__', <bound method Test.__init__ of <__main__.Te ct at 0x01E55750>>), ('__le__', <method-wrapper '__le__' of Test object at 0x01E55750>), ('__ <method-wrapper '__lt__' of Test object at 0x01E55750>), ('__module__', '__main__'), ('__ne__ hod-wrapper '__ne__' of Test object at 0x01E55750>), ('__new__', <built-in method __new__ of ject at 0x5D9B61A0>), ('__reduce__', <built-in method __reduce__ of Test object at 0x01E55750 _reduce_ex__', <built-in method __reduce_ex__ of Test object at 0x01E55750>), ('__repr__', <m rapper '__repr__' of Test object at 0x01E55750>), ('__setattr__', <method-wrapper '__setattr_ est object at 0x01E55750>), ('__sizeof__', <built-in method __sizeof__ of Test object at 0x01 ), ('__str__', <method-wrapper '__str__' of Test object at 0x01E55750>), ('__subclasshook__', -in method __subclasshook__ of type object at 0x02536030>), ('__weakref__', None), ('method', method Test.method of <__main__.Test object at 0x01E55750>>)]
inspect モジュールの getmembers() でインスタンスの全メンバを取得してますが、_Test__member、_Test__privateMethod が存在していることが確認できますね。
・29.12. inspect — 活動中のオブジェクトの情報を取得する — Python 3.4.3 ドキュメント
http://docs.python.jp/3.4/library/inspect.html#inspect.getmembers
以上になります。