【中級者向け】 Pythonのimport *って何?

python_logo

どうも、こんにちは!

Pythonのライブラリを使っている時ってimport対象をついつい省略するために*を使ってしまうんですよね。。

とっても便利だけど、これって何をしてるんだろう・・?

考えてみると意外と難しいですよね。

実を言うと、答えはモジュールかパッケージかの違い__all__が握っているんです!

おさらいとして

モジュールは2通りの呼び出し方法があります。

忘れてしまった方は以下の記事で復習できますよ!

その2通りの呼び出しの内の1つが以下のようなコードです。

import foo from object

これのobjectを*(ワイルドカード)にすることで全てのオブジェクトを使えるといいましたが、厳密に言うと違います。

以下の4パターンになります。

  • __all__がある場合:モジュールの場合
  • __all__がある場合:パッケージの場合
  • __all__がない場合:モジュールの場合
  • __all__がない場合:パッケージの場合

それではそれぞれみていきましょー!

__all__がある場合

__all__で記述されている内容だけがインポートされます。

ディレクトリの構成は次のように考えてみましょう。



.
├── caller.py
└── package
    ├── __init__.py
    ├── moduleA.py
    └── moduleB.py

コードは以下になります。

モジュールの場合

モジュールの中で__all__にimportされるオブジェクトがlistとして書いてあります。

今回の例でいうとmoduleB.pyを実行してみましょう。
dir()は現在定義されているオブジェクトを表示する関数です。

実行すると以下のように表示されます。


['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__','__loader__', '__name__','__package__', '__spec__','test1']

__all__で定義したtest1の関数だけがここに格納されています!

パッケージの場合

パッケージの__init__.pyの中に__all__にインポートされるモジュールがlistで書いてあります。

それではmoduleB.pyを実行してみましょう。


['__annotations__', '__builtins__', '__cached__','__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'moduleA']

__all__がない場合

これはモジュールかパッケージかによって動作が異なりますので注意してください

ディレクトリの構成は先ほどと同じです。


.
├── caller.py
└── package
    ├── __init__.py
    ├── moduleA.py
    └── moduleB.py

コードは以下になります。

モジュールの場合

アンダースコア(_)で始まる名前を除く全てのオブジェクトを全てインポートします。

アンダースコアは変数の中でしか使いませんよっていう宣言ですので、使ってもいいやつは全てインポートされます(こういった変数をプライベート変数といいます)。

先ほどと同様にmoduleB.pyを実行してみましょう。

実行すると以下のように表示されます。


['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'test1', 'test2']

_privateを除くオブジェクトがインポートされていますね!

パッケージの場合

fromで指定したパッケージのみをインストールします

それではcaller.pyを実行してみましょう。


['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']

一つもモジュールはインポートされていないことがわかります。

これは直感的ではないですよね。
ワイルドカード使ってんだから全部とってきてよ!!って感じですよね 笑

ですが、大きなパッケージになると相当数のモジュールやサブパッケージが含まれています。
それを処理するのはかなり時間がかかるので、こういった実装になっているのです。

import *は意識する必要はほぼない

普通に使う分には問題ないのです!
開発者としてパッケージを作成して世の中にリリースする場合は考慮すればいいって感じですね。

ですが、この記法はあまりよくないです。
単純にいって、使わないオブジェクトを組み込むわけですからね。必要ないものは極力ないほうがソースコードって読みやすいんですよ。
ですので使うのはインタープリターでの実行だけに留めておきましょう。
ただ、こういう書き方もあるのだという認識で大丈夫です。

以上になります。この記事であなたがよりよいPython生活を送れることを祈ってます!