モジュール¶
モジュールとは関数やクラスなどを別ファイルで利用できる状態で整理した Python のソースコードのことです。これまでのソースコードは実行することを念頭に実装しましたが、モジュールは別のファイルから取り込まれることを念頭に実装を行います。
モジュールの書き方¶
拡張子 .py を持った通常の Python ファイルとして作成すれば問題ありません。ただしシバンはモジュールを実装するときには不要です。たとえ書いても悪さをすることはありませんが、実行するスクリプトとしては使用しないので書く意味はあまりありません。
フィボナッチ数列 0, 1, 1, 2, 3, 5, 8, ... を出力するような関数 fib(n) をモジュールとして書いてみましょう。
fib.py
def fib(n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a + b
print()
fib.py を別のファイル main.py に取り込んでこの関数を実行するには次のように書きます。
main.py
#!/usr/bin/env python
import fib # fib.py を取り込む
def main():
fib.fib(10) # fib.py 内の fib() を呼び出す
if __name__ == '__main__':
main()
モジュール作成の注意点¶
Python のコードは必ずしも関数内に含める必要はなく、ファイル内に直接処理を書くこともできます。
fib.py
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a + b
print()
しかしこの状態で main.py から import fib をすると import した時点でフィボナッチ数列を出力する処理が突然実行されてしまいます。こういった問題が起こらないようにモジュールとして提供する機能は基本的に関数やクラスにまとめておく必要があります。
from-import¶
モジュール内の関数やクラスにアクセスするときは モジュール名.関数名 のように . を使ってアクセスしますが、モジュール名や関数名が長くなってくると少し書き方が面倒になります。こういうときは from 文を使って参照名を短くすることができます。
from (モジュール名) import (関数名)
このようにすると モジュール名.関数名 としていたところが 関数名 だけで参照できるようになります。
#!/usr/bin/env python
from fib import fib # fib.py 内の fib() をインポート
def main():
fib(10) # fib() を呼び出す
if __name__ == '__main__':
main()
ただし import fib とインポートしたときは fib.py 内のすべての関数やクラスが参照できるのに対し、 from fib import fib は fib() のみが参照できます。複数の定義をインポートしたいときは次のようにします。
from (モジュール名) import (関数名), (関数名), ...
モジュール内の全定義をまとめて from でインポートしたければ次のようにします。
from (モジュール名) import *
ただしこのインポート文は余計な定義をインポートしてしまう恐れがあるため推奨されません。モジュールのインポート方法は次の優先度で検討して下さい。
| おすすめ | インポート文 |
|---|---|
import (モジュール名) |
|
from (モジュール名) import (関数名) |
|
from (モジュール名) import * |
__name__¶
__name__ は Python で使用できる隠し変数の 1 つで、モジュール名を表す文字列が入っています。例えば foo.py というモジュールであれば __name__ は 'foo' になります。
import foo
print(foo.__name__) # 'foo'
しかしこの変数がモジュール名になるのは別のモジュールからインポートされたときだけです。foo.py を直接実行した場合は __name__ には '__main__' が入ります。
foo.py
#!/usr/bin/env python
print(__name__)
$ python foo.py
__main__
つまり __name__ の値がモジュール名になるのか '__main__' になるのかを見ることでインポートされようとしているのかどうかを判断することができるようになります。
Hello, World! のソースコードで出てきた
if __name__ == '__main__':
main()
という構文は自分がインポートされてないときだけ main() を呼び出すという意味になります。 __name__ の値を見ることで 1 つのファイルで実行スクリプトとモジュールの両方を実装することができるようになります。