この質問は、以前に質問された this oneとthis one に基づいていますが、より微妙な点、具体的には「内部クラス」とは何ですか?
これが私の状況です。クラスの多くが外部で構築されることを意図していない MS Office ファイルを操作するための Python ライブラリを構築していますが、それらのメソッドの多くは API の重要な部分です。例えば:
class _Slide(object):
def add_shape(self):
...
_Slide
ライブラリのエンドユーザーとして、 を呼び出して新しいスライドを取得しますPresentation.add_slide()
。ただし、スライドを作成したら、必ずadd_shape()
. したがって、メソッドは API の一部ですが、コンストラクターはそうではありません。プレゼンテーション クラスだけが外部/API コンストラクターを持つため、この状況はライブラリーで何十回も発生します。
PEP8 はこの点であいまいであり、何が内部クラスと見なされるかを詳しく説明せずに「内部クラス」に言及しています。この場合、クラスは「部分的に内部」であると言えると思います。
問題は、少なくとも 3 つの異なる状況を区別するための表記が 2 つしかないことです。
- クラスのコンストラクターと「public/API」メソッドはすべて使用可能です。
- コンストラクターは使用されませんが、クラスの「public/API」メソッドは使用されます。
- このクラスは実際には内部的なものであり、パブリック API はありません。将来のリリースで変更または削除する権利を留保します。
コミュニケーションの観点から、外部 API (ライブラリーのエンドユーザー対象) と内部 API (開発者対象) の明確な表現の間には矛盾があることに注意してください。エンド ユーザーにとって、通話_Slide()
は禁止/自己責任です。_random_helper_method()
ただし、これは内部 API のハッピー メンバーであり、内部からのみ呼び出されるべきものとは異なります_Slide()
。
この質問について、私に役立つ可能性のある視点はありますか? エンドユーザー API の明確さのために戦うためにクラス名に「一重アンダースコア」の弾薬を使用することが慣例で定められているのでしょうか、それとも、クラス API が実際にいつ使用されるかについて自分自身や他の開発者に伝えるためにそれを予約してもよろしいでしょうか?たとえば、変更される可能性のある実装の詳細であるため、それが存在するモジュールの外部のオブジェクトによって使用されませんか?
更新:数年間のさらなる熟考の後、モジュール (ファイル) の外部のクラスとしてアクセスすることを意図していないクラスに名前を付けるときに、先頭にアンダースコアを使用するという規則に落ち着きました。このようなアクセスは通常、そのクラスのオブジェクトをインスタンス化するため、またはクラス メソッドにアクセスするためなどです。
これは、モジュールのユーザー (多くの場合、もちろん自分自身です:) に基本的な指標を提供します。(単体テスト モジュールはこの規則の例外です。このようなインポートは、「内部」クラスの単体テストによく現れる場合があります。)
これはclassへのアクセスであることに注意してください。おそらくファクトリなどによって提供される、モジュールの外部のそのクラス (型)のオブジェクトへのアクセスは完全に問題なく、おそらく期待されています。クラスから作成されたオブジェクトとクラスを区別できなかったことが、最初の混乱の原因だったと思います。
from module import *
この規則には、ステートメントを作成するときにこれらのクラスを含めないという副次的な利点もあります。私自身のコードでこれらを使用することはなく、避けることをお勧めしますが、これらのクラス識別子はモジュール インターフェイスの一部になることを意図していないため、これは適切な動作です。
これは何年にもわたる試行錯誤の末の私の個人的な「ベスト プラクティス」であり、もちろん「正しい」方法ではありません。あなたのマイレージは異なる場合があります。