この記事では、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()
実行結果
インスタンス変数