プライベートメンバ

慣習的な命名規則によるプライベートメンバ

以前のページで書いたとおり、Pythonにはアクセス修飾子がありません。

また、公式ドキュメントでも、「オブジェクトの中からしかアクセス出来ない “プライベート” インスタンス変数は、 Python にはありません。」と記述されています。

そのかわり、慣習的にアンダースコアで始まる名前 (例えば_xなど)のメンバは、プライベートなメンバとみなします

あくまでもそうみなす、というだけなのでアクセス自体は可能です。

__変数名による隠蔽

また、「アンダースコア2つで始まり、末尾がアンダースコア1つ以下」となる変数名の場合、その変数に対して外部からアクセスするとAttributeErrorを発生させることができます。

class Sample():
    def __init__(self):
        self.a = 0
        self._b = 0
        self.__c = 0
        self.__d_ = 0
        self.__e__ = 0


obj = Sample()
a = obj.a # アクセス可能
b = obj._b # アクセス可能
c = obj.__c # AttributeError発生
d = obj.__d_ # AttributeError発生
e = obj.__e__ # アクセス可能

上のサンプルでは、a、_bはアクセス可能です。_bはアンダースコアから始まっていますが、アクセスできてしまう点に注意してください。

また、__c、__d_は外部からアクセスすると、AttributeErrorが発生します。

ただし、2つ以上のアンダースコアで終わるメンバはプライベートメンバとはなりません。(__init__や__next__などが該当しますね。)

このため、__e__は名前の末尾がアンダースコア2つで終わるのでアクセス可能です。

とはいえ、前述の通り、完全なプライベート変数は存在しません。実は以下の方法よりアクセスできてしまいます。

c = obj._Sample__c # アクセスできてしまう

この原理について興味がある方は以下を参照してください。

http://docs.python.jp/3.5/tutorial/classes.htmlより引用
クラスのプライベートメンバについて適切なユースケース(特にサブクラスで定義された名前との衝突を避ける場合)があるので、マングリング(name mangling) と呼ばれる、限定されたサポート機構があります。 __spam (先頭に二個以上の下線文字、末尾に一個以下の下線文字) という形式の識別子は、 _classname__spam へとテキスト置換されるようになりました。ここで classname は、現在のクラス名から先頭の下線文字をはぎとった名前になります。このような難号化 (mangle) は、識別子の文法的な位置にかかわらず行われるので、クラス定義内に現れた識別子全てに対して実行されます。

名前のマングリングは、サブクラスが内部のメソッド呼び出しを壊さずにメソッドをオーバーライドするのに便利です。