Pythonにおいて __init__ やや __main__ は様々なところで出てくる。
部分的に覚えるのは良いが、各それぞれに対して目的があるので曖昧に同じような意味と誤解しないため覚えておいた方がよいと思います。
ですので、各場所でどのようなことをしているのか一覧化します。
1. __main__.py
このファイルはPythonパッケージををスクリプトとして実行することができます。
よく実行用のファイルとして定義されるmain.pyとは別物です。
簡単に実行例を示します。
demo
├── __init__.py
├── __main__.py
└── echo.py
python3 -m echo
from . import echo
echo.echo("__init__ から実行")
from .echo import echo
echo("__main__.pyから実行")
def echo(text="not text"):
print(text)
__init__.pyから実行
__main__.pyから実行
上記のような構成でスクリプトのように実行した場合、__init__.pyと__main.pyファイルが実行される。
今度はプログラム上からパッケージを呼び出すようにプロジェクト構成を以下のように替え、main.pyを実行してみる。
demo
├── __init__.py
├── __main__.py
└── echo.py
main.py
import demo
python3 main.py
__init__.pyから実行
上記の実行結果のように__init__.pyのみ実行され__main__.pyは実行されない。
これをみてmain.pyでいいんじゃないかと思うが、パッケージに実行用にファイルを用意しているため、例にあるmain.pyファイルから__main__.pyは参照できないようになっている。
2. __name__ == '__main__'
実行ファイルにパッケージとしてimportで読みだされた時に実行されないように、条件式でコマンドラインベースで直接呼び出されたかを判定させるために使用する。
基本的な使い方は以下のように用いる。
def main():
...
if __name__ == '__main__':
main()
print(__name__)
>>> __main__
上記のように書くことでコマンド上でpython main.pyのように実行した時に、__name__ == '__main__'の条件がTrueになるため、main関数を実行することができる。
逆にmain.pyファイルを別の箇所から読みだしてみる。
下記のようなファイルを用意し、python call.pyを実行する。
そうすると、mainと出力され表示され、拡張子なしのファイル名が表示される。
import main()
>>> main
3. __init__.py
このファイルがあるフォルダをPythonパッケージとして認識させるためにあるファイル。モジュール検索をする名前空間の目印の役目を持っている。そのため、以下のようなフォルダ構成があるとするとdir3をimportするにはimport dir1.dir2.dir3と書くことでdir3を読み込むことができる。
ちなみに同階層にある場合は fron . import xxのようにピリオドで現在位置を指定できる。
dir1
├── __init__.py
└── dir2
├── __init__.py
└── dir3
└── __init__.py
また、__init__.py内に書かれたコードはimprtされた時点で実行される。
3. def __init__(self): ...
Classからインスタンスを生成する際に実行するコンストラクタと呼ぶ初期化するメソッドです。
以下に実行例を示します。インスタンスを生成したときに呼び出されるため、A()と実行したものにはインスタンス生成と表示される。
A.call()のようにインスタンスを作成せずに実行するとインスタンス生成は表示されず、callのみが表示される。
@staticmethosというデコレータは指定することでインスタンスと紐づかずにメソッド実行することができるようになる。
Class A:
def __init__(self):
print('インスタンス生成')
@staticmethod
def call():
print('call')
a = A()
>>> インスタンス生成
A()
>>> インスタンス生成
A.call
>>> call