Pythonの__init__.pyは省略せずに作成しよう

## __init__.pyとは？

まず`__init__.py`とは、Pythonのディレクトリをパッケージとして認識させるためのファイルです。これにより、ディレクトリ内のモジュールをパッケージの一部として管理できるようになります。

### 1. **パッケージの認識**
   - `__init__.py`は、ディレクトリをPythonの**パッケージ**として認識させるためのファイルです。
   - パッケージとは、モジュールをまとめて整理するためのディレクトリのことです。
   - Python 3.3以降では、`__init__.py`がなくてもディレクトリはパッケージとして認識されますが、特別な初期化処理を行いたい場合や、古いバージョンとの互換性を確保したい場合には依然として使用されます。



### 2. **初期化処理**
   - パッケージがインポートされる際に実行される初期化コードを記述できます。
   - 例えば、必要なモジュールやクラスのインポート、設定の初期化、ログの設定などを行うことができます。

   ```python
   print("mypackage is imported")

   from .module1 import func1
   from .module2 import Class2
   ```

   上記の例では、`mypackage`をインポートすると`module1`の`func1`や`module2`の`Class2`を直接使えるようになります。


### 3. **名前空間の整理**
   - パッケージの公開インターフェースを整理する役割もあります。
   - 不要な内部モジュールを隠したり、パッケージのユーザーにとって重要な機能だけをエクスポートすることができます。

   ```python
   __all__ = ["func1", "Class2"]
   ```

   `__all__`を指定すると、`from mypackage import *`のような形でインポートする際に指定された名前だけがインポートされます。


### 4. **パッケージの階層化**
   - サブパッケージを持つパッケージでは、親と子のパッケージ間でインポートを整理する役割も果たします。
   - 親パッケージがサブパッケージを動的に読み込む際にも活用できます。


### 5. **空の`__init__.py`**
   - `__init__.py`が空の場合もあります。この場合、そのディレクトリが単なるパッケージであることを示し、特別な初期化処理を行わないという意味になります。

---
## **`__init__.py`って必要？ - 省略して困った話**

以前、「書かなくても動いてしまうから省略してもいいのかな？」と思った事がありました。しかし、実際に省略したことで以下の問題に直面しました。

1. **unittest がテストモジュールを認識しない**
   - `unittest discover` を使ってテストを実行しようとしたところ、一部のテストが実行されませんでした。
   - `__init__.py` を追加したら正常に動作しました。

2. **Lint ツールがモジュールを正しく検出しない**
   - `flake8` や `mypy` を実行すると、一部のモジュールが `ModuleNotFoundError` になった。
   - `__init__.py` を追加したらエラーが解消。

3. **複数のモジュールが存在するプロジェクトで import エラーが発生**
   - `from mypackage import module1` のような `import` が動作しないことがあった。
   - `__init__.py` を入れたら問題なく動作した。

この経験から、「`__init__.py` を省略すると、意図せず Namespace Package の機能を使ってしまうことになる」と実感しました。以降、面倒くさがらずに `__init__.py` を作成するようにしています。

---

## Python 3.3以降では省略しても問題ない？

Python 3.3 では、**PEP 420** によって「Implicit Namespace Package」が導入されました。これにより、`__init__.py` がなくても Python のパッケージとして認識されるようになりました。

**ただ、実際には省略せずに`__init__.py`を作成するが正しいです。**

PEP 420 (Implicit Namespace Package) の内容を詳しく見てみると、**「`__init__.py` を省略してもパッケージとして認識される」** という点が強調されているため、これが「`__init__.py` は不要になった」と誤解される原因になったと考えられます。



### **PEP 420 の主なポイント**
PEP 420 の公式ドキュメントでは、以下のような内容が紹介されています。

### **1. `__init__.py` を省略してもパッケージとして認識される**
PEP 420 では、以下のように明記されています。

> **"A package is now simply a directory that is a container for modules or subpackages."**  
> （パッケージは単に、モジュールやサブパッケージを含むディレクトリになった）

以前は `__init__.py` が必須だったのに対し、**「ディレクトリであればパッケージとして扱われる」** という説明がされているため、これを見た開発者は **「もう `__init__.py` を作らなくてもよい」** と思ってしまう可能性があります。

---

### **2. `sys.path` にある複数のディレクトリを統合できる**
PEP 420 の主な目的は、**Namespace Package** のサポートです。例えば、以下のようなディレクトリ構造があったとします。

```
/usr/lib/python3.3/site-packages/mypackage/
    module1.py

/home/user/project/mypackage/
    module2.py
```

この場合、Python 3.3 以前は `__init__.py` がないと `mypackage` はパッケージとして認識されませんでした。しかし、PEP 420 では `__init__.py` がなくても `mypackage` というパッケージが統合され、以下のように `import` できるようになります。

```python
import mypackage.module1
import mypackage.module2
```

これが「`__init__.py` は不要」と誤解される理由の一つです。

---

### **3. `__init__.py` を使うべき場面の説明が不十分**
PEP 420 では、**Namespace Package は通常のパッケージとは異なるもの** であることが説明されていますが、**「従来のパッケージでは `__init__.py` を作成するのが推奨される」** という点が強調されていません。

そのため、以下のような誤解が生じます。

❌ **誤解**：「Python 3.3 以降は `__init__.py` を作らなくてもいい」  
✅ **本来の意図**：「Namespace Package では `__init__.py` を省略できるが、通常のパッケージでは `__init__.py` を作るべき」

---

### **`__init__.py`を省略することによる弊害**
1. **`import`が遅くなる可能性**：
   - Namespace Packageは通常のパッケージと異なる仕組みでモジュールを探索するため、処理が遅くなる場合がある。
   - 探索順序の違いから問題が発生するリスクもある。

2. **ツールの非対応**：
   - `unittest`などの標準ツールは、`__init__.py`のないディレクトリをモジュールとして認識しない。
   - 自動でモジュールを探すツール（例: Linter）もNamespace Packageに対応していない場合が多い。

3. **効率低下のリスク**：
   - Namespace Package対応のために、すべてのディレクトリを再帰的に探索すると、処理速度が低下する。
   - 特に大量のファイルが含まれるディレクトリ（例: `node_modules`）やネットワーク上のディレクトリでは、探索が極めて遅くなる。

---

### **結論**
- **`__init__.py`を明示的に記述することが推奨**される。
- Namespace Packageは特殊なケース向けで、一般的なパッケージ開発では使うべきではない。