Categories: Python

【Python】プライベートな属性の定義【マングリング】

この記事では、Pythonでプライベートな属性を定義する方法を解説します。

クラスにプライベートな属性を定義することで外部から参照できない属性を定義することができます。ちなみに、属性を隠蔽することを「カプセル化」と言います。

それでは、プライベートな属性を定義する方法を見ていきましょう!

プライベートな属性の実装方法

プライベートな属性は、_(アンダーバー)を識別子の先頭に1つ記述して定義します。

class TestClass:
    _cv = 'クラス変数'
    def __init__(self):
        self._ic = 'インスタンス変数'
    
    def _method(self):
        return 'メソッド'

上記ではプライベートなクラス変数、インスタンス変数、メソッドを定義しました。

外部から呼び出せるか試してみましょう!

tc = TestClass()
print(tc._cv, tc._ic, tc._method())

実行結果

クラス変数 インスタンス変数 メソッド

全部普通に呼び出せてしまいました。
実はPythonでは、完全にプライベートな属性を定義できないんです!

先頭にアンダーバーを 1つ付けるのは慣習であり、言語的な強制力はありません。なので、先ほど定義した属性たちは「プライベートとして扱おう属性」です。

使用しているエディタによっては、アンダーバーを付けることでその属性が候補に表示されなくなったりします。

マングリング

識別子の前にアンダーバーを2つ付けることでプライベートっぽい属性を定義できます。

class TestClass:
    __cv = 'クラス変数'
    def __init__(self):
        self.__ic = 'インスタンス変数'
    
    def __method(self):
        return 'メソッド'

外部から呼び出せるか試してみます。

tc = TestClass()
print(tc.__cv, tc.__ic, tc.__method())

実行結果

AttributeError: 'TestClass' object has no attribute '__cv'

エラーを見てみると「TestClassオブジェクトには、__cvという属性は無いよ!」とのことです。

これはプライベートにできたわけではなく、「マングリング」によって属性名が_クラス名__識別子の形に置換されたのでエラーが発生しているに過ぎません。

試しに置換された形で属性を呼び出してみると...

tc = TestClass()
print(tc._TestClass__cv, tc._TestClass__ic, tc._TestClass__method())

実行結果

クラス変数 インスタンス変数 メソッド

普通に呼び出せます!

完全にプライベートというわけではありませんが、誤って呼び出してしまうことはありえないのでプライベートな属性として扱うことができます。

ちなみに、クラス内部からは__属性名の形で呼び出すことができます。

class TestClass:
    def __init__(self):
        self.__ic = 'インスタンス変数'
    
    def method(self):
        print(self.__ic)


tc = TestClass()
tc.method()

実行結果

インスタンス変数

まとめ

この記事では、Pythonの属性をプライベートにする方法を解説しました。

  • Pythonでは完全にプライベートな属性は実装できない
  • 慣習的に属性の前に「_(アンダーバー)」を付ける
  • マングリングを使うことで誤って呼び出すことを防げる

っていう感じですね!

それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ

ゆうまる

独学でプログラミングを勉強しているおじさん。いろんな言語を勉強したが浅く広くなためあまり仕事につながらない。また忘れっぽいため自分のブログを備忘録としても使っている。産まれてこのかたずっとネコを飼ってる生粋のネコ派。最近お腹が出てきて筋トレに奮闘中!

Recent Posts

【Dart】コンストラクタのデフォルト引数について

Dartのコンストラクタのデフォルト引数…

2週間 ago

【Unity】有料アセットを無料で手に入れる方法

この記事では、Unityの有料アセットを…

4か月 ago

【Python】任意の秒数だけ処理を一時停止する方法【sleep()関数】

この記事では、Pythonで任意の秒数だ…

1年 ago

【Python】Wordの文書の新規作成と読み書き

この記事では、Pythonを使ってWor…

1年 ago

【Python】メタクラスって結局なんなの?

この記事では、Pythonのメタクラスに…

1年 ago