Python

【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())

実行結果

Traceback (most recent call last):
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では完全にプライベートな属性は実装できない
  • 慣習的に属性の前に「_(アンダーバー)」を付ける
  • マングリングを使うことで誤って呼び出すことを防げる

っていう感じですね❗️

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

最短3か月でエンジニア転職『DMM WEBCAMP COMMIT』