web-dev-qa-db-ja.com

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

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

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

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

83
Erik

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

例:

./dir/__init__.py

import something

./test.py

import dir
# can now use dir.something

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

EDIT2:dgrantは、私の例で混乱の可能性を指摘しました。 __init__.pyimport 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で割り当てられたすべての名前は、インポートされたモジュール、関数、またはクラスにかかわらず、パッケージまたはパッケージ内のモジュールをインポートするたびにパッケージ名前空間で自動的に使用可能になります。

71

それは本当に個人的な好みであり、pythonモジュールのレイアウトに関係しています。

erikutilsというモジュールがあるとします。モジュールになる方法は2つあります。sys.patherikutils.pyというファイルがあるか、または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 *フィールドクラスは__init__.pyDjango/db/models/fieldsディレクトリに定義されています。すべてを仮想的なDjango/db/models/fields.pyモデルに詰め込みたくなかったので、彼らはこれをやったと思うので、いくつかのサブモジュールに分割しました(関連.pyfiles.pyなど)、作成された* Field定義をfieldsモジュール自体に貼り付けました(したがって、__init__.py)。

34
dgrant

__init__.pyファイルを使用すると、内部のパッケージ構造を外部から見えなくすることができます。内部構造が変更された場合(たとえば、1つのファットモジュールを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

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

29
nikow