2

次のモジュール構造を持つPythonで小さなパッケージを書いています

package/
  __init__.py
  cls1.py
  cls2.py
  cls3.py
  mod1.py
  mod2.py

それぞれclsN.pyに単一のクラスClsNがあり、それぞれmodN.pyにそれらのクラスを使用するさまざまな関数が含まれています。インポート構造を次のようにしたい

package
package.Cls1
package.Cls2
package.Cls3
package.mod1
package.mod1.func1
...
package.mod2
package.mod2.func2
...

名前空間を汚染することなく。現在、 と を介してこれらのクラスのいずれかにアクセスできるという問題がpackage.Cls1ありpackage.cls1.Cls1、 で定義されているすべてのものpackage/cls1.py(インポートを含む) にもアクセスできます。変数を設定しようとしました__all__が、その間以外は何もしないようですfrom package import *。Python がclsNサブモジュールとして表示されないようにする方法はありますか? それとも、これらのファイル内のインポートを非表示にする方法ですか? ライブラリのユーザーが各クラスにアクセスする方法が 2 つあるのは望ましくありません。

4

2 に答える 2

4

stdlib には、このような場合に対処する 2 つの方法があります。

1 つ目は簡単です: 他の属性を private とマークするのと同じ方法で、プライベート モジュールを private とマークするだけです: アンダースコア プレフィックスを使用します。これはそれらをユーザーから隠しているわけではありませんが、ユーザーがそれらを使用すべきではないことを示しています (また、iPython や PyDev などでそれらを補完として提供することを妨げる可能性があります)。通常はこれで十分です。

これに関する唯一の実際の問題は、モジュール名のアンダースコア プレフィックスも、それらがネイティブ アクセラレータであることを暗示する傾向がある_fooことfoomodule.cです_foo.py

もう 1 つの方法は、それらをインポートせずに使用するかfrom submodule import name, other, yetanotherdelモジュールの最後で使用することです。package.Cls1などと明示的に同じ型になりたいという事実はpackage.cls1.Cls1、これがまさにあなたが望むものであることを意味します。

ユーザーは、必要に応じて明示的にインポートできます。しかし、Python は通常、悪意や意図的な愚かさをブロックする方法を提供していないため、試みるべきではありません。

于 2013-07-09T19:35:16.967 に答える
2

まず、どこから何が見えるかはあまり気にしないことをお勧めします。ユーザーが にアクセスしようとしてpackage.mod1.Cls1、それが機能するかどうかは本当に問題ですか? Python は一般的にかなり寛大な言語であり、何かを隠そうとすることは、多くの場合、価値があるよりも面倒です。

とはいえ、標準外のアクセスを少しでも少なくしたい場合は、アンダースコアで始まる別の名前でクラスをモジュールにインポートすることをお勧めします。名前の先頭に単一のアンダースコアがある変数はインポートされfrom _ import *ず、リストにも表示されませんdir。これを行う方法は次のとおりです。

mod1.py

from .Cls1 import Cls1 as _Cls1
from .Cls2 import Cls2 as _Cls2
from .Cls3 import Cls3 as _Cls3

次に、モジュールのコードでアンダースコア名を使用します。クラスにアクセスしたい他のコードは、おそらく「公式」の場所でそれらを見つけに行くでしょう。

于 2013-07-09T19:30:13.130 に答える