__init__.pyの__all__

__all__ の使用方法を説明するために、簡単な例を挙げてみましょう。想定するパッケージ構造は以下の通りです:

my_package/ __init__.py 
                      module_a.py 
                      module_b.py

ここで、module_a.pymodule_b.py があるとします。

module_a.py

# module_a.py

def public_function():
    print("これは公開関数です。")

def _private_function():
    print("これは非公開関数です。")


module_b.py(__all__ を使用)

# module_b.py

__all__ = ["public_function_b"]

def public_function_b():
    print("これはmodule_bの公開関数です。")

def _private_function_b():
    print("これはmodule_bの非公開関数です。")

__init__.py

# __init__.py

from .module_a import *
from .module_b import *

module_b.py__all__ を定義しているため、from my_package import * を実行すると、module_bpublic_function_b のみがインポートされます。一方で、module_a.py では __all__ を定義していないため、public_function_private_function が両方ともインポートの対象となりますが、通常、アンダースコア (_) で始まる関数や変数は非公開(プライベート)として扱われ、外部からのインポートを意図していないことが多いです。

以下のように、my_package を使用する外部スクリプトからインポートを試みると、この挙動が確認できます。

# 外部スクリプト

from my_package import *

public_function()  # module_aのpublic_functionが呼び出される
public_function_b()  # module_bのpublic_function_bが呼び出される

_private_function_private_function_b は、__all__ の定義によってフィルタリングされているため(または慣習によって非公開とみなされているため)、この方法ではインポートされません。

この例からわかるように、__all__ を使うことでモジュールやパッケージから公開されるシンボルを明示的に制御でき、外部からアクセス可能なAPIの範囲を定義するのに役立ちます。これにより、内部実装の詳細を隠蔽しつつ、必要な機能のみを提供することが可能になります。

この記事が気に入ったらサポートをしてみませんか?