問題の歴史
クラシックなオブジェクト指向プログラミングにおいて、カプセル化は内部データへのアクセス制限を通じて実現されます。ほとんどの言語には厳密なアクセス修飾子がありますが、Pythonには「みんな大人だから」という原則があり、厳密なプライバシーは存在しません。
問題
開発者はPythonにおける保護された(_protected)およびプライベート(__private)属性とメソッドを混同し、「ダブルアンダースコア」が完全な保護を提供すると考えたり、全く保護がないと考えたりしています。
解決策
Pythonは協約を実装しています:シングルアンダースコア _var は保護されたものであり、ダブルアンダースコア __var はプライベート(名前マングリングが行われる)です。そのため、こうした属性やメソッドへのアクセスは可能ですが、難しくなります:_ClassName__varとして呼び出されます。
コードの例:
class Example: def __init__(self): self._protected = 1 # 保護された self.__private = 2 # プライベート(名前マングリング) ex = Example() print(ex._protected) # 1 #print(ex.__private) # AttributeError print(ex._Example__private) # 2(名前マングリング)
主な特徴:
インスタンスを通じて「プライベート」フィールドにアクセスすることはできますか?
はい、マングリングを通じて:_ClassName__varです。したがって、データは利用可能ですが、暗黙的です。
継承時にプライベートメソッド/属性はどうなりますか?
名前マングリングは、子クラスが親のプライベート要素を偶発的にオーバーライドすることを防ぎますが、_ParentClass__attrを介してアクセスすることはできます。ダブルアンダースコアのメソッドは、子クラスからは「見えません」。
class A: def __foo(self): print("A") class B(A): def bar(self): # self.__foo() — エラー self._A__foo() # 動作する
PythonにはJVM/C++レベルの完全なプライバシーがありますか?
いいえ。すべては協約とマングリングに基づいています。データを完全に保護することはできません。Pythonは動的に任意の属性へのアクセスを許可します。
大きなライブラリでユーザーがダブルアンダースコアを使ってプライベート属性を変更しようとしたが、これは「秘密」だと思っていましたが、_ClassName__varを介して変更は引き続き発生しました。
利点:
欠点:
プロジェクト内で内部フィールドにはシングルアンダースコアを使用し、クラスの外からは触れないことに合意しました。安全なアクセスのためにプロパティを追加しました。
利点:
欠点: