[解決済み】Pythonの「private」メソッドは、なぜ実際にはprivateではないのですか?
2022-03-23 14:31:13
質問
Pythonでは、クラス内に「プライベート」メソッドや変数を作成する機能があります。名前の前にアンダースコアを2つ付けると、次のようになります。
__myPrivateMethod()
. では、これをどう説明すればいいのでしょうか。
>>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
>>> obj.myPublicMethod()
public method
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!
どうしたんだ!?
よくわからなかった人のために、少し説明します。
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
publicメソッドとprivateメソッドを持つクラスを作成し、インスタンス化します。
次に、そのpublicメソッドを呼び出す。
>>> obj.myPublicMethod()
public method
次に、そのプライベートメソッドを呼び出してみる。
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
ここではすべてがうまくいっているように見えますが、呼び出すことができません。実は「プライベート」なのです。まあ、実際にはそうではないのですが。実行中 dir() は、Pythonがすべての'private'メソッドに対して魔法のように作成する、新しい魔法のメソッドを明らかにします。
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
この新しいメソッドの名前は、常にアンダースコア、クラス名、メソッド名の順になります。
>>> obj._MyClass__myPrivateMethod()
this is private!!
カプセル化はこれくらいにして、え?
いずれにせよ、Pythonはカプセル化をサポートしていないと聞いていたのですが、それならなぜ試してみたのでしょうか?どうなんでしょう?
どうすれば解決するの?
名前のスクランブルは、サブクラスが誤ってスーパークラスのプライベート・メソッドや属性をオーバーライドしないようにするために使用されます。外部からの意図的なアクセスを防ぐためのものではありません。
例えば
>>> class Foo(object):
... def __init__(self):
... self.__baz = 42
... def foo(self):
... print self.__baz
...
>>> class Bar(Foo):
... def __init__(self):
... super(Bar, self).__init__()
... self.__baz = 21
... def bar(self):
... print self.__baz
...
>>> x = Bar()
>>> x.foo()
42
>>> x.bar()
21
>>> print x.__dict__
{'_Bar__baz': 21, '_Foo__baz': 42}
もちろん、2つの異なるクラスが同じ名前であれば、それは破綻しています。
関連
-
Python関数の高度な応用を解説
-
pyCaret効率化乗算器 オープンソース ローコード Python機械学習ツール
-
任意波形を生成してtxtで保存するためのPython実装
-
[解決済み】socket.error: [Errno 48] アドレスはすでに使用中です。
-
[解決済み] builtins.TypeError: strでなければならない、bytesではない
-
[解決済み] 'DataFrame' オブジェクトに 'sort' 属性がない
-
[解決済み] Pythonのリストメソッドであるappendとextendの違いは何ですか?
-
[解決済み] Pythonでシングルトンを作成する
-
[解決済み] mixinとは何か、なぜ有用なのか?
-
[解決済み】Rubyにあって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 実装 サイバーパンク風ボタン
おすすめ
-
Python 人工知能 人間学習 描画 機械学習モデル作成
-
pyCaret効率化乗算器 オープンソース ローコード Python機械学習ツール
-
[解決済み] [Solved] sklearn error ValueError: 入力に NaN、infinity または dtype('float64') に対して大きすぎる値が含まれている。
-
[解決済み】「RuntimeError: dictionary changed size during iteration」エラーを回避する方法とは?
-
[解決済み】csv.Error:イテレータはバイトではなく文字列を返すべき
-
[解決済み】Flask ImportError: Flask という名前のモジュールがない
-
[解決済み】ValueError: pickleプロトコルがサポートされていません。3、python2 pickleはpython3 pickleでダンプしたファイルを読み込むことができない?
-
[解決済み】Python - "ValueError: not enough values to unpack (expected 2, got 1)" の修正方法 [閉店].
-
[解決済み] Pythonの "Private"(実装)クラス
-
[解決済み】pythonでプライベートモジュール関数を定義する