[解決済み] Pythonのprivateメソッドとprotectedメソッドの継承
質問
Pythonには「本当の」private/protectedメソッドがないことは知っています。このアプローチは何かを隠すためのものではなく、私はただPythonが何をするのかを理解したいだけです。
class Parent(object):
def _protected(self):
pass
def __private(self):
pass
class Child(Parent):
def foo(self):
self._protected() # This works
def bar(self):
self.__private() # This doesn't work, I get a AttributeError:
# 'Child' object has no attribute '_Child__private'
つまり、'protected' メソッドは継承されるが、'private' メソッドは全く継承されないということでしょうか?
それとも何か見落としているのでしょうか?
どのように解決するのですか?
Pythonにはプライバシーモデルがありません。C++、C#、Javaのようなアクセス修飾子はありません。本当に「protected」または「private」属性はありません。
先頭のダブルアンダーコアと末尾のダブルアンダーコアがない名前は
が混同されます。
を使用して、継承時の衝突を防いでいます。サブクラスは独自の
__private()
メソッドを定義することができ、これらは親クラス上の同じ名前と干渉することはありません。このような名前は
クラスのプライベート
と見なされます。これらはまだクラスの外部からアクセス可能ですが、偶然に衝突する可能性ははるかに低くなります。
マングリングは、そのような名前の前に余分なアンダースコアとクラス名(その名前がどのように使われるか、またはそれが存在するかどうかにかかわらず)を付けることによって行われ、事実上、それらに
名前空間
. で
Parent
クラスでは、任意の
__private
の識別子は (コンパイル時に)
_Parent__private
であるのに対し
Child
クラスでは、識別子は
_Child__private
で、クラス定義のいたるところにあります。
以下のようにするとうまくいきます。
class Child(Parent):
def foo(self):
self._protected()
def bar(self):
self._Parent__private()
参照 識別子の予約クラス を字句解析のドキュメントに追加しました。
__*
クラスのプライベートな名前。このカテゴリの名前は、クラス定義のコンテキスト内で使用される場合、ベースと派生クラスの "private" 属性間の名前の衝突を避けるために、マングルドフォームを使用するように書き直されます。
と参照される の名前に関するドキュメント :
プライベートネームの揶揄 : クラス定義にテキストで現れる識別子が、2つ以上のアンダースコアで始まり、2つ以上のアンダースコアで終わらない場合、そのクラスのプライベート名とみなされます。プライベート名は、コードが生成される前に長い形式に変換されます。この変換では、先頭のアンダースコアを削除し、アンダースコア 1 つを挿入したクラス名を名前の前に挿入します。たとえば、識別子
__spam
という名前のクラスで発生する識別子は、次のように変換されます。_Ham__spam
. この変換は、識別子が使用される構文的な文脈に依存しません。
以下の場合を除いて、クラス・プライベート名を使用しないでください。 特に を使用することで、クラスをサブクラス化しようとする開発者に、特定の名前を使用することはできない、あるいはクラスを破壊するリスクがあると伝える必要がなくなるからです。公開されているフレームワークやライブラリ以外では、この機能を使用することはほとんどありません。
この機能は PEP 8 Python スタイルガイド には、プライベート名のマングリングについて次のような記述があります。
クラスがサブクラス化されることを想定しており、サブクラスに使わせたくない属性がある場合 がある場合、その名前に で命名することを検討してください。これは Pythonの名前マングリングアルゴリズムが呼び出され、そこでクラスの名前が属性名にマングリングされます。 を属性名にマングルします。これは属性名の衝突を避けるのに役立ちます。 これは、サブクラスが同じ名前の属性を含んでいる場合に、属性名の衝突を避けるのに役立ちます。 を含む場合、属性名の衝突を避けることができます。
注1: マングル化された名前では単純なクラス名のみが使用されることに注意してください。 従って、サブクラスが同じクラス名と属性名の両方を選択した場合、名前の衝突が発生する可能性があります。 の両方を選択した場合、名前の衝突が発生する可能性があります。
注意2: 名前のマングリングは、デバッグなどの特定の用途や
__getattr__()
のような、ある種の使い方を不便にすることがあります。しかし、名前マングリングのアルゴリズム はよく文書化されており、手動で実行するのも簡単です。注3:誰もが名前のマングリングを好むわけではありません。偶発的な名前の衝突を避ける必要性と、高度な呼び出し元が使用する可能性とのバランスをとるようにしてください。 偶発的な名前の衝突を避けることと、上級の呼び出し元が使用する可能性のバランスを取るようにしてください。
関連
-
[解決済み] staticmethodとclassmethodの違いについて
-
[解決済み] Javaにおけるpublic、protected、package-private、privateの違いは何ですか?
-
[解決済み] Pythonのリストメソッドであるappendとextendの違いは何ですか?
-
[解決済み] Pythonの静的メソッド?
-
[解決済み] 私的相続、公的相続、保護相続の違いについて
-
[解決済み] パブリック、プライベート、プロテクトの違いは何ですか?
-
[解決済み] Pythonで子クラスから親クラスのメソッドを呼び出すにはどうすればよいですか?
-
[解決済み】Pythonに三項条件演算子はありますか?
-
[解決済み] 小数点以下1桁を取得する[重複]。
-
[解決済み] Ctrl-CでPythonスクリプトを終了できない
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] DataFrameの文字列、dtypeがobjectの場合
-
[解決済み] Pythonのマルチプロセッシングプールimap_unorderedの呼び出しの進捗を表示しますか?
-
[解決済み] PythonでファイルのMD5チェックサムを計算するには?重複
-
[解決済み] googletransがエラー 'NoneType' オブジェクトに 'group' 属性がない、と言って動かなくなった。
-
[解決済み] タプルのリストを複数のリストに変換するには?
-
[解決済み] python-requests モジュールからのすべてのリクエストをログに記録します。
-
[解決済み] PyMongoで.sortを使用する
-
[解決済み] あるオブジェクトが数であるかどうかを確認する、最もパイソン的な方法は何でしょうか?
-
[解決済み] Flaskで非同期タスクを作る
-
[解決済み] Pythonの検索パスを他のソースに展開する