Pythonの「プライベート」(実装)クラス


106

2つの部分で構成される小さなPythonモジュールをコーディングしています。

  • 公開インターフェースを定義するいくつかの関数、
  • 上記の関数で使用される実装クラスですが、モジュールの外部では意味がありません。

最初は、この実装クラスを使用して関数内に定義することにより、この実装クラスを「隠す」ことにしましたが、これは読みやすさを妨げ、複数の関数が同じクラスを再利用する場合は使用できません。

では、コメントとドキュメント文字列に加えて、クラスを「プライベート」または「内部」としてマークするメカニズムはありますか?アンダースコアのメカニズムは知っていますが、理解すると、変数、関数、メソッド名にのみ適用されます。

回答:


174

単一の下線プレフィックスを使用します。

class _Internal:
    ...

これは「内部」シンボルに関する公式のPython規約です。「from module import *」は、アンダースコアが前に付いたオブジェクトをインポートしません。

編集:単一の下線の規則への参照


3
アンダースコアのルールがクラスに適用されることは知りませんでした。インポート時に名前空間が乱雑になりたくないので、この動作を探していました。ありがとう!
oparisy 2009

1
これは「公式の」Python規約であると述べているので、リンクを付けるとよいでしょう。ここの別の投稿では、すべてが公式の方法であり、ドキュメントにリンクしています。
フロディン2009

11
python.org/dev/peps/pep-0008-_single_leading_underscore:弱い「内部使用」インジケーター。たとえば、「from M import *」は、名前がアンダースコアで始まるオブジェクトをインポートしません。-内部使用のクラスには先行アンダースコアがあります
Miles

2
大手アンダースコアは、内部のようなものをマークするための規則であるのに対し、「これを台無しにしない」すべてが必ずしも意味せずに、より多くの「Mインポートから*」で使用できるように設計されたモジュール用で、そのモジュールのユーザーすべきではないタッチそのクラス。
マイル

65

要するに:

  1. プライバシーを強制することはできません。Pythonにはプライベートクラス/メソッド/関数はありません。少なくとも、Javaなどの他の言語のように厳格なプライバシーではありません。

  2. プライバシーの提示/提案のみが可能です。これは慣例に従います。クラス/関数/メソッドをプライベートとしてマークするためのPythonの慣習は、その前に_(アンダースコア)を付けることです。たとえば、def _myfunc()またはclass _MyClass:。また、メソッドの前に2つのアンダースコアを付けて、疑似プライバシーを作成することもできます(例:)__foo。メソッドに直接アクセスすることはできませんが、クラス名(例:)を使用して特別な接頭辞を介して呼び出すことはできます_classname__foo。したがって、あなたができる最善のことは、それを強制するのではなく、プライバシーを示す/提案することです。

この点でPythonはperlに似ています。Perlの本からプライバシーに関する有名な言葉を言い換えると、哲学は、ショットガンで守られているからではなく、招待されていないからといって、居間を離れるべきだということです。

詳細については:


#1に対応して、メソッドのプライバシーを強制することができます。__method(self)のような二重のアンダースコアを使用すると、クラスの外からはアクセスできなくなります。しかし、Foo()._ Foo__method()のように呼び出すことで回避する方法があります。私はそれをより難解な名前に変更しているだけだと思います。
エヴァンフォスマルク2009

1
その見積もりは正確です。
Paul Draper


10

私が時々使用するパターンはこれです:

クラスを定義します。

class x(object):
    def doThis(self):
        ...
    def doThat(self):
        ...

クラスのインスタンスを作成し、クラス名を上書きします。

x = x()

機能を公開するシンボルを定義します。

doThis = x.doThis
doThat = x.doThat

インスタンス自体を削除します。

del x

これで、パブリック関数のみを公開するモジュールができました。


2
「クラス名を上書きする」の目的・機能を理解するのに少し時間を要しましたが、そのときはとても笑顔になりました。いつ使うかわかりません。:)
ザック・ヤング

このテクニックに名前はありますか?
ビシュワシュミシュラ


4

デザイン規約の問題に対処するため、そしてクリストファーが言ったように、Pythonには「プライベート」というものは本当にありません。これは、C / C ++のバックグラウンド(しばらく前のように)から来た人にとってはねじれたように聞こえるかもしれませんが、最終的には、次の規則で十分だと気付くでしょう。

アンダースコアが前にあるものを見るのは、それを直接使用しないのに十分なヒントです。乱雑なhelp(MyClass)出力(クラスの使用方法を検索するときに誰もが目にするもの)に関心がある場合、下線付きの属性/クラスはそこには含まれていないため、「パブリック」インターフェースが記述されるだけになります。

さらに、すべてのものを公開することには、たとえば、外部からほとんど何でもユニットテストできる(C / C ++プライベートコンストラクトでは実際には実行できない)など、独自の素晴らしい特典があります。


4

2つのアンダースコアを使用して、「プライベート」識別子の名前にプレフィックスを付けます。モジュール内のクラスの場合は、単一の先行アンダースコアを使用します。これらは、「from module import *」を使用してインポートされません。

class _MyInternalClass:
    def __my_private_method:
        pass

(Pythonには本当の「プライベート」というものはありません。たとえば、Pythonは自動的にクラスメンバーの名前を2つのアンダースコアで自動的にマングルします。そのため、マングルされた名前が__clssname_mymemberわかっている場合は、とにかく「プライベート」エンティティを使用できます。 。ここを参照してください。もちろん、必要に応じて、「内部」クラスを手動でインポートすることもできます)。


なぜ2つの_なのですか?1つで十分です。
S.Lott、2009

「インポート」がクラスと関数をインポートしないようにするには、単一の下線で十分です。Pythonの名前マングリング機能を導入するには、2つのアンダースコアが必要です。より明確である必要があります。編集しました。
chroder

さて、フォローアップです。なぜマングリングに名前を付けるのですか?そのことの潜在的な利点は何ですか?
S.Lott、2009

5
考えられる利点は、これらの変数にアクセスする必要がある他の開発者を困らせることです:)
Richard Levasseur '15
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.