【Python入門】クラスのインスタンス変数を隠す(マングリング)

クラスのインスタンス変数を設定した際に、通常の状態だと簡単にアクセスできます。

簡単にサンプルを書いてみます。
sampleA.pyというファイルで、クラス名はA。
インスタンス変数にself.xを設定し、self.xに代入したり取り出すためにゲッターとセッターも用意する。

class A:
    def __init__(self, x):
        self.x = x

    @property
    def foo(self):
        return self.x

    @foo.setter
    def foo(self, x):
        self.x = x

>>> import sampleA
>>> a = sampleA.A(10)
>>> a.foo
10
>>> a.x  # 直接ゲットできる
10
>>> a.foo = 20
>>> a.foo
20
>>> a.x
20
>>> a.x = 30  # セッター使わなくてもセットできる
>>> a.foo
30
>>> a.x
30

def __init__でクラスAの初期化が行われる。
これは a = sampleA.A(10)を実行した時にクラスAのインスタンスが作成されたタイミングで呼ばれる。
sampleA.A(10)によってself.x = 10 というのが走ったことになる。

でも、このself.xというのは全く隠れていないので簡単に直接アクセスできてしまう。
@propertyによってゲッターを、@foo.setterによってセッターを定義したのに、そんなのすっ飛ばして直接出し入れできるのだからかたなしだ。

結論から言うと、クラス定義の外から見えないようにするためには2つのアンダースコア(__)が必要だ

class A:
    def __init__(self, x):
        self.__x = x  # ダブルアンダースコア

    @property
    def foo(self):
        return self.__x

    @foo.setter
    def foo(self, x):
        self.__x = x


>>> import sampleA
>>> a = sampleA.A(10)
>>> a.foo
10
>>> a.__x  # 直接アクセスできない
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute '__x'

@propertyでゲッターメソッド、@hogehoge.setterでセッターメソッドを定義できる。
ゲッターとセッターを定義するからには、直接インスタンス変数にアクセスしてほしくないだろうから、アンダースコア2つを使って直接アクセスを禁止する。

@properyのように@を利用するものをデコレータという。
デコレータの利点は、メソッドの中身を編集したとしても、そのメソッドを扱う側は特に変更する必要がなくなる点にある。