__init__.pyにコードを追加する


85

djangoのモデルシステムがどのように機能するかを調べていると、理解できないことがわかりました。

空の__init__.pyファイルを作成して、現在のディレクトリがパッケージであることを指定していることを知っています。また、__init__.pyimport *が正しく機能するように変数を設定できます。

しかし、djangoはfrom ... import ...ステートメントの束を追加し、のクラスの束を定義し__init__.pyます。どうして?これは物事を乱雑に見せるだけではありませんか?このコードが必要な理由はあり__init__.pyますか?


13
これは本当にDjangoについてではありませんか?はい、Djangoで最初に見ましたが、これは純粋なPythonのもののように見えます。おそらく、Djangoタグは実際には適切ではありません。
S.Lott 2008

__init__.pydjango1.8にインポートステートメントが表示されません。これは古いバージョン用でしたか?もしそうなら、どのバージョン?
ゴビダス2017年

回答:


72

のすべてのインポートは、__init__.pyそれを含むパッケージ(ディレクトリ)をインポートすると利用可能になります。

例:

./dir/__init__.py

import something

./test.py

import dir
# can now use dir.something

編集:言及するのを忘れました__init__.py、そのディレクトリからモジュールを最初にインポートするときにのコードが実行されます。したがって、通常は、パッケージレベルの初期化コードを配置するのに適した場所です。

EDIT2:dgrantは、私の例では混乱の可能性があることを指摘しました。中には、__init__.py import somethingパッケージから必要に応じて、任意のモジュールをインポートすることができません。たとえば、これをに置き換えることができますimport datetime。そうすると、トップレベルtest.pyでこれらのスニペットの両方が機能します。

import dir
print dir.datetime.datetime.now()

そして

import dir.some_module_in_dir
print dir.datetime.datetime.now()

__init__.pyつまり、インポートされたモジュール、関数、クラスなど、で割り当てられたすべての名前は、パッケージまたはパッケージ内のモジュールをインポートするたびに、パッケージ名前空間で自動的に使用可能になります。


わかりました、ありがとう。しかし、クラスを追加するのが良い考えである理由はまだわかり__init__.py ません。これらのクラスの初期化コードはあまり考慮していません(ただし、それについては間違っているかもしれません)。
エリック

これらはおそらく、パッケージを操作するたびに役立つクラスです。しかし、私は推測したくありません。客観的であるかどうかにかかわらず、そこにある理由はたくさんあります:)
Alexander Kojevnikov 2008

13
これは、歴史的な理由による場合もあります。モジュールをパッケージに、module.pyをmodule / __ init__。pyに変換する場合、既存のすべてのコードで以前と同じように使用できますが、モジュールにサブモジュールを含めることができるようになりました。
–Łukasz

1
モジュールは親を__init__.py暗黙的に実行します。内部のモジュールをインポートすることにより、__init__.py循環インポートを作成しています。その__init__.pyようなインポートの前に、は完全には実行されません。__init__.py空にしておく方が安全です。
Ivo Danihelka 2010

これは__init__.pyファイルに固有のものではないことに注意することが重要です。あなたがあなたのdir/other.pyようなものを持っているファイルを持っていたなら、from datetime import datetimeあなたはまた呼び出すことができるでしょう、dir.other.datetime.now()あるいはfrom dir.other import datetime
カルレスサラ2016

37

これは本当に個人的な好みであり、Pythonモジュールのレイアウトと関係があります。

というモジュールがあるとしましょうerikutils。そこには、モジュールとすることができるという二つの方法があり、どちらかが呼ばれるファイル持っerikutils.pyあなたのsys.pathディレクトリが呼び出されたりerikutilsあなたのsys.path空と__init__.pyその内部のファイルを。そして、あなたが呼ばれるモジュールの束を持っているとしましょうfileutilsprocutilsparseutilsとあなたはそれらの下にサブモジュールになりたいですerikutils。したがって、fileutils.pyprocutils.py、およびparseutils.pyという名前の.pyファイルをいくつか作成します。

erikutils
  __init__.py
  fileutils.py
  procutils.py
  parseutils.py

たぶん、あなただけではない属しを行い、いくつかの機能を持っているfileutilsprocutilsまたはparseutilsモジュールを。そして、と呼ばれる新しいモジュールを作成したくないとしましょうmiscutils。そして、次のように関数を呼び出せるようにします。

erikutils.foo()
erikutils.bar()

するのではなく

erikutils.miscutils.foo()
erikutils.miscutils.bar()

のでので、erikutilsモジュールは、ディレクトリ、ファイルではなく、我々は内部のそれの機能を定義する必要があります__init__.pyファイル。

djangoで、私が考えることができる最良の例はdjango.db.models.fieldsです。すべてのdjango * Fieldクラスは__init__.pydjango / db / models / fieldsディレクトリのファイルで定義されています。私は、彼らは架空のに塾のすべてのものにしたくなかったので、彼らはこれをしたと思いますジャンゴ/ DB /モデル/ fields.pyモデル、彼らは(いくつかのサブモジュールにそれを分割するので、related.pyfiles.py例えば、)と彼らは、作成された* Field定義をfieldsモジュール自体に貼り付けました(したがって、__init__.py)。


1
dgrant、私が意味したのはsomething、外部モジュールである可能性があるということです。dir.somethingは機能します。コメントありがとうございます。投稿を編集してわかりやすくします。
アレクサンダーコジェフニコフ2008

29

この__init__.pyファイルを使用すると、内部パッケージ構造を外部から見えなくすることができます。内部構造が変更された場合(たとえば、1つのfatモジュールを2つに分割したため)、__init__.pyファイルを調整するだけで済み、パッケージに依存するコードは調整できません。パッケージの一部を非表示にすることもできます。たとえば、一般的な使用の準備ができていない場合などです。

このdelコマンドを使用できるため、一般的な例__init__.pyは次のようになります。

from somemodule import some_function1, some_function2, SomeObject

del somemodule

ここでsomemodule、新しいものを分割することにした場合は、次の__init__.pyようになります。

from somemodule1 import some_function1, some_function2
from somemodule2 import SomeObject

del somemodule1
del somemodule2

外から見ると、パッケージは以前とまったく同じように見えます。


1
@Arlen:ポイントは、パブリックAPIの一部ではないということです。モジュールの名前を変更すると、依存するコードが壊れないようにすることができます。さらに、これにより、たとえばイントロスペクションを使用してAPIドキュメントを自動的に作成する場合など、API要素が1回だけ表示されるようになります。
nikow 2011

5
@Arlen:モジュールを削除すると、モジュールをimport <pack>.somemodule1直接削除できなくなります。、および削除されていないサブモジュール<pack>で定義またはインポートされたオブジェクトからのみインポートできます__init__.py
MestreLion 2012
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.