目的
前回までは関数について学んだ.Pythonでは関数はモジュールやパッケージとして管理することができる.ここではモジュールとパッケージについて学ぶ.
説明
モジュール
モジュールの作成とインポート
2つの数値データを受け取り,加算を行う関数,減算を行う関数,乗算を行う関数,除算を行う関数の定義と呼び出しは以下のようになる.
数多くの関数を定義した場合,全てを1つのファイルに記述する代わりに,いくつかのファイルに記述することがある.関数の定義の集合(あるいはそれを記述したファイル)をモジュールと呼ぶ.
ここでは,上記の例でモジュールを作ってみよう.加減乗除を行う関数を定義している部分とその他の部分を2つのファイル(ここでは「my_module.py」と「main.py」とする)に分け,同じディレクトリに置く.
「main.py」を実行すると,以下のようなエラーが表示され,モジュールの関数が呼び出せないことがわかる.
モジュールの関数を呼び出すには,呼び出すファイル中でモジュールをインポートする必要がある.ファイル名「my_module.py」から拡張子を除いた「my_module」がモジュール名となるため,「import my_module」と記述すると,モジュールがインポートできる.モジュール中の関数を呼び出すには,モジュール名の後ろに「.」とつけて関数名を記述すればよい.例えば,以下のようにすると,モジュール中の関数を呼び出すことができる.
別名をつけてインポートする
モジュール名が長いときなどには,モジュール名に短い別名をつけてインポートすることがある.
モジュール中の一部の関数をインポートする
モジュールにはいくつかの関数の定義が記述されている.全ての関数を使用しない場合には,一部の関数だけをインポートすることができる.例えば,以下のようにすると,my_moduleモジュールのadd関数とsubtract関数だけをインポートでき,モジュール名は書かずに関数名だけで関数を呼び出すことができる.
パッケージ
複数の関数を1つにまとめたものがモジュールであるが,モジュールを階層構造にして1つにまとめたものがパッケージである.例えば画像処理ライブラリや機械学習ライブラリは数多くの関数からなっている.これらのライブラリでは,よく似た関数を1つのモジュールにまとめ,複数のモジュールを階層構造にして管理している.モジュールとパッケージの関係は,ファイルとディレクトリの関係と同じである.数多くのファイルをうまく管理するには,ディレクトリを使用して階層構造で管理するとよいのと同じである.
ここでは,以下のような名前の階層構造で2つのパッケージディレクトリと2つのモジュールファイルを作る.
2つのモジュールファイルには,以下のように,それぞれ2つの関数があり,いずれも簡単な文字列を出力する関数とする.
Pythonでは,パッケージがインポートされたときに初期化を行うために,初期化の処理内容を記述した「__init__.py」という名前のファイルをパッケージディレクトリに置く必要がある.ここでは,以下の2箇所に内容が空の「__init__.py」を置く.
最後に,my_packageディレクトリと同じ階層に,以下の内容の「main.py」を置き,各パッケージの各モジュールの各関数を呼び出す.
以下のように表示され,正しく各関数が呼び出されていることがわかる.
モジュールのインポート時の動作とモジュール名変数
モジュールのインポート時の動作
以下のように,身長と体重からBMIを求める関数bmiと身長から標準体重を求める関数standart_weightがあり,それを呼び出しているプログラムphysical.pyがあるとする.
physical.pyを実行すると,以下のようにBMIと標準体重が表示される.
このbmi関数を他のプログラムbmi.pyから呼び出して使用したいとき,physical.pyをモジュールとしてインポートすればよいであろう.まず,インポートだけしてみよう.以下のようにインポート文だけ記述したbmi.pyを用意し
bmi.pyを実行すると,以下のようにBMIと標準体重が表示される.これは,インポートをしたときに,physical.pyモジュールの20行目が実行され,その結果全ての関数が実行されてしまったためである.
インポートするだけでは何も実行されないようにするには,physical.pyを以下のように書き換えればよい(この理由は後で説明する).
インポート文だけを記述したbmi.pyを再度実行すると,何も表示されなくなる.
次に,bmi.pyを以下のように書き換え,bmi関数を呼び出すと,
正しくbmi関数が呼び出されたことがわかる.
モジュール名が保存される変数__name__
では,なぜ「if __name__ == ‘__main__’:」と記述すればよかったのかを考えよう.
Pythonには自動的に値が代入される特別な変数がいくつかあり,__name__変数はその1つである.physical.pyを以下のように書き換え,__name__変数を表示して,代入されている値を確認してみよう.
physical.pyを実行すると,以下のように表示され,__name__変数には「__main__」という文字列が代入されていることがわかる.
次に,physical.pyモジュールをインポートしただけのbmi.pyを用意し,
bmi.pyを実行すると,以下のようにモジュール名「physical」が表示される.このことから,__name__変数にはモジュール名である「physical」という文字列が代入されていることがわかる.
まとめると,実行されたファイル中で__name__変数を参照すると「__main__」とうい文字列が,呼び出されたモジュールファイル中で__name__変数を参照するとモジュール名が代入されていることがわかる.したがって,__name__変数に代入されている値を確認すれば,あるファイルが直接実行されたか,他のファイルからモジュールとして呼び出されて実行されたかを区別することができる.そのため,「if __name__ == ‘__main__’:」と記述すれば,そのファイルが直接呼び出されたときだけ実行し,他のファイルからモジュールとして呼び出されたときには実行しない処理を記述することができる.
以上の理由から,複数の関数が定義されているプログラムでは,以下のようにmainの処理を書くことがある.
課題
課題0
名前・年齢・趣味・血液型からなるリストを渡すと,様々な自己紹介文を表示する関数群をモジュールとして作成し,各関数を呼び出せ.
課題1
以下の関数群からなるモジュールを作成し,各関数を呼び出せ.
- 身長を渡すと標準体重を返す関数
- 身長と体重を渡すと標準体重より重いか軽いかを表示する関数
- 身長と体重を渡すとBMIを返す関数
- 身長と体重を渡すと太っているか標準かやせているかを表示する関数
課題2
以下の関数群からなるモジュールを作成し,各関数を呼び出せ.
- 英語・数学・国語・理科・社会の試験の点数からなるリストを渡すと平均を返す関数
- 英語・数学・国語・理科・社会の試験の点数からなるリストを渡すと最も良い教科の点数と最も悪い教科の点数を返す関数
- 英語・数学・国語・理科・社会の試験の点数からなる辞書を渡すと平均を返す関数
- 英語・数学・国語・理科・社会の試験の点数からなる辞書を渡すと最も良い教科の点数と最も悪い教科の点数を返す関数
課題3
課題0・課題1・課題2のモジュールからなるパッケージを作成し,各モジュールのいくつかの関数を呼び出せ.