Python

【Python初心者】別ファイルの関数やクラスの実行(モジュール化)

こんにちは(@t_kun_kamakiri)(‘◇’)ゞ

この記事では、Pythonで関数やクラスのモジュール化について解説します。
前回の記事で「クラスの基本定義」について解説しましたのでまだ見ていない方は是非どうぞ(^^)/

前回の記事はこちら

 

この記事はこんな人のために書きました。

この記事を読むと
  • Pythonで関数やクラスのモジュール化をしたい
  • プログラムの機能ごとにファイルを分けたい
モジュール化についてとても基本的なことをまとめましたので参考にしてください。
使用環境を示しておかないと混乱しそうなのでちゃんと書いておきます(^^)/

【Pythonの使用環境について】
今回はファイル分けを行ってPythonを実行するので、エディタを使ってコードを書いていきます。

 

関連記事
☟書籍も紹介しておきます。
こちらの本がPython初心者が挫折することなく勉強できる本です。
(本記事のようのPython使用環境と異なりますが、とてもわかりやすいので全く問題ありません)
スポンサーリンク

ファイルのダウンロード

今回解説する内容に関しては既にコードを作成していますのでそちらをお使いください。

ファイルのダウンロードはこちら

ダウンロードができたら適当なところで解凍をしておきましょう。

mainファイルに関数を書く

では、さっそく本題に入っていきますが・・・・
いきなり関数のモジュール化をやってもイメージがつかないと思いますので、ひとつひとつ順を追って理解していきましょう

まずはtest001でべた書きでメインファイルにコードを書いてみましょう。

test001

ここではまだモジュール化をしておらず、メインのファイルに関数を直接ベタ書きする場合を示しています。

main.py

では、こちらを実行してみましょう。

実行はコマンドプロンプトかVisual Studio CodeにのPower shellで

と打てば実行されます。

【実行結果】

「if __name__ == ‘__main__’:」で何をしているのかわかりにくいかと思ったので、「print(f’__name__ は{__name__}となっている。’)」と出力して__name__がどのような値を取っているのかを確認してみました。

「__name__ は__main__となっている。」となっていると出力されているので、__name__が__main__となっていることがわかりますね。

これは__name__が実行されたモジュール名が値として格納されるので、実行されたファイル(今回はmain.pyですが名前は何でも良い)なら__name__=__main__となっているわけです。

これがメインファイルにベタ書きでコードを書いた場合です。

モジュール化:関数を別ファイルに分ける

関数を別ファイルに分けてmain.pyから呼び出す方法はいくつかあります。
ここでは代表的なものを3つ紹介します。

  1. from get_math import get_trialgle, get_circle
  2. from get_math import *
  3. import get_math 
  4. import get_math as g

test002:

今度は関数を別のファイルに分けてみましょう。

ファイル構成は以下のようになっています。

get_math.py

呼び出される方のファイル内で__name__ がどうなっているのかを確認するために「print(f’__name__ は{__name__}となっている。’)」と出力してみましょう。

main.py

メインファイルがかなりすっきりしているなっていますね。

実行はコマンドプロンプトかVisual Studio CodeにのPower shellで

と打てば実行されます。

【実行結果】

  • get_math.pyでは「__name__」はそれ自身のファイル名になっています。
  • main.pyの中でget_math.pyの中の関数を使うためには、
    「from get_math import get_trialgle, get_circle」という記述をファイルの先頭に書いています。

    今回は関数を使うためimportの後は関数名を書きましたが、後ほどやるようにクラスを設定することもできます。
  • 別ファイルの関数を使うときはget_trialgle(10, 2)として使うだけ。

このようにしてmainのファイルはやりたいことをただ記述するだけでよく、複雑なアルゴリズムは別ファイルに分けておくと便利ですよね。
ユーザーにとって別ファイルの複雑なアルゴリズムがメインのファイルに書かれているとちょっと見る気を失せてしまいますし(‘_’)

test003: from get_math import *

test002では「from get_math import get_trialgle, get_circle」と書き「get_math の中の関数get_trialgleとget_circleを呼び出しますよ」と宣言しましたが、


という書き方をして「get_math」ファイルの中のすべての関数/クラスを呼び出しますという書き方もできます。

main.py

※get_math.pyの変更はありません。

出力結果はtest002と同じですがtest003のmain.pyの「from get_math import *」のような書き方はお勧めをしません。

  • どのモジュールに属する関数/クラスを使用しているのかが不明瞭
  • 「import *」ですべての関数/クラスをインポートしているのでメモリ消費を無駄にしている

以上の理由から「import *」 という書き方はしないようにしましょう。

test004 : import get_math

モジュールだけインポートする書き方もできます。

main.py

冒頭に「import get_math」とだけ書き「 get_math」の中の関数を使う場合は、「get_math.get_trialgle(10, 2)」と書いてドット(.)でつなげて関数を呼び出します。

※get_math.pyの変更はありません。

出力結果はtest002と同じですがtest003よりは良い書き方かと思います。

test005 : import get_math as g

test004ではモジュール内の関数を呼び出すときに「get_math.get_trialgle(10, 2)」と書いていましたが、get_mathと書くのが邪魔くさい感じがしますね。
そんなときは略語で以下のように記述することができます。

これは「get_math を gと略します」という宣言になります。

なので、関数を呼び出すときに、

get_math.get_trialgle(10, 2)

g.get_trialgle(10, 2) 

かなりコードがすっきりしますね。

main.py

※get_math.pyの変更はありません。

以上で別ファイルから関数を呼び出す3つの記述方法を紹介しました。

  1. 〇 from get_math import get_trialgle, get_circle
  2. × from get_math import *
  3. △ import get_math 
  4. 〇 import get_math as g

お勧めとしては①と④の方法かと思います。
③もよく使うので問題ない書き方です。

パッケージ化:複数のファイルをフォルダに分ける

複数のモジュール(ファイル)がある場合、コードの規模が多くなって名前が被ってしまうこともおります。
そこで複数のモジュール(ファイル)をひとまとめにした仕組みがパッケージです。

カマキリ

モジュールとかパッケージがよくわからない?

モジュールとかパッケージとかちょっと曖昧な表現をされるとわかりにくいのですよね。

  • モジュール:ファイル
  • パッケージ:フォルダ

絵で描くと以下のようなイメージです。

パッケージ(フォルダ)の中に複数のサブパッケージ(フォルダ)があり、その中に複数のモジュール(ファイル)が存在しているということです。

※今回はパッケージはひとつだけにします。

test006

ファイル構成は以下のようにします。

  • メインファイル(main.py)
  • パッケージ(フォルダ):myget_math
    モジュール(ファイル):get_math.py

main.py

メインファイルはパッケージかからモジュールを呼び出すために冒頭で「from myget_math import get_math」と書いています。

このような書き方ですね。

モジュール(ファイル)の中の関数を使うときはドット(.)でつなげていくだけなので、「get_math.get_trialgle(10, 2)」とすれば関数を呼び出すことができます。

※get_math.pyの変更はありません。
※結果もtest002から変更がありません。

test007

次はtest006とファイル構成が同じでmain.pyからパッケージ内のモジュールの呼び出し方を変えてみましょう。

パッケージからモジュールをインポートする宣言をしています。

main.py

モジュール(ファイル)内の関数を呼び出すのにimportで書いた記述をドットでつなげていくので「myget_math.get_math.get_trialgle(10, 2)」と書きます。

ちょっと長い記述になってしまいましたがこちらも正常に動作する正しい記述です。

※get_math.pyの変更はありません。
※結果もtest002から変更がありません。

test008

test007で関数を呼び出すのに「myget_math.get_math.get_trialgle(10, 2)」と長い記述を書きましたが、以下のような略語を設定すれば記述がすっきりします。

これで「myget_math.get_math」が「g」と名前付けされています。

main.py

これでモジュール(ファイル)内の関数を呼び出すのに「g.get_trialgle(10, 2)」と書けばよく、とてもすっきりした記述になりますね。

※get_math.pyの変更はありません。
※結果もtest002から変更がありません。

test009

次にファイル構成を以下のようにします。

test007~test008とどこが変わったかというと、パッケージ(フォルダ)「myget_math」内に「__init__.py」というファイルを用意しました。

main.py

main.pyでこのように書き、「import myget_math」というパッケージ(フォルダ)をインポートしただけでは以下のようなエラーが出てしまします。

これは「myget_math」がモジュールとして認識されてしまいその中に「get_math」という属性が存在しないというエラーです。

今回「myget_math」はモジュールではなくパッケージとして認識する必要があるので、「import myget_math」としたときにパッケージ内で最初に実行されるファイルというのを用意しておきます。

それが「__init__.py」です。
「__init__.py」を「myget_math」内に用意します。

main.pyが実行されるとmain.pyの冒頭「import myget_math」がインポートされ、「myget_math」内の「__init__.py」が実行され、「from myget_math import get_math」によりモジュールがインポートされるという仕組みです。

※get_math.pyの変更はありません。

少し難しいですが実行してみればどういう動作をしているのかがわかるでしょう。

実行はコマンドプロンプトかVisual Studio CodeにのPower shellで

と打てば実行されます。

【実行結果】

「__init__.py」に「print(‘====実行された====’)」という記述を書いたので「from myget_math import get_math」のモジュールがインポートされたあとに「’====実行された====」という出力がされています。

test010

今度はパッケージ内に複数のファイルを用意してみます。

パッケージ「myget_math」内に、もう一つモジュール「get_math_multi.py」を追加しました。

main.py

__.init__.py

「from . import get_math」という書き方をしています。
「from .」のドット(.)は現在のフォルダに対して「get_math.py」をインポートするという意味です。
現在のフォルダは「__init__.py」がいるフォルダのことなので「myget_math」の事ですね。

「myget_math/get_math.py

「myget_math/get_math_multi.py

実行はコマンドプロンプトかVisual Studio CodeにのPower shellで

と打てば実行されます。

【実行結果】

このようにパッケージ(フォルダ)何に複数のモジュール(ファイル)を用意することができます。

test011

次はtest010と同じファイル構成で「__init__.py」を以下の書き換えます。

__.init__.py

test010では2行になっていたのを1行にまとめました。

※その他のファイルは変数なし
※結果はtest010と同じ

クラスにまとめる

今までは「myget_math」というパッケージ内に「get_math.py」と「get_math_multi.py」というモジュールを用意しましたが、大きなくくりでいうと2つのモジュールは何かを計算している機能を持ったプログラムというくくりにできるため、これらをクラスという形でまとめておきます。

test012

今度はパッケージ内に複数のファイルを用意してみます。

test011にはパッケージ内に2つのモジュールがありましたが今回は「get_math_multi.py」だけにしています。
その代わりにクラスを用いて複数の関数を持つようなコードに書き換えました。

「myget_math/get_math_multi.py」

__.init__.py

「from .get_math_multi import CalcMath」という書き方をしています。
「from .get_math_multi」のドット(.)は現在のフォルダ内のget_math_multiモジュールを読み込むという意味です。
さらに、「import CalcMath」でCalcMathクラスをインポートしています。

main,py

「calc = myget_math.get_math_multi.CalcMath(10, 100, 1000)」でクラスのインスタンス化を行っています。

引数に「CalcMath(10, 100, 1000)」と入れてクラスが実行されたときに実行される初期化関数「def __init__(self, base, height, radius):」を「myget_math/get_math_multi.py」内で使っています。

実行はコマンドプロンプトかVisual Studio CodeにのPower shellで

と打てば実行されます。

【実行結果】

このようにパッケージ(フォルダ)何に複数のモジュール(ファイル)を用意することができます。

test013

最後はtest012でmain.pyの冒頭に「import myget_math」と書いていたために、クラスのインスタンス化で「calc = myget_math.get_math_multi.CalcMath(10, 100, 1000)」とドット(.)でつなぐのが長くなっていたの以下のように略語で使うように書き換えます。

こうすると記述がすっきりしますね。

main.py

コードがすっきりしましたね。

さらに今回のmain.pyは複数条件で計算が行えるように以下のように辞書型で2つの条件を書いています。

これを以下のfor文で繰り返し処理を行うようにしました。

実行はコマンドプロンプトかVisual Studio CodeにのPower shellで

と打てば実行されます。

【実行結果】

複数条件での結果が出力されましたね(^^♪

まとめ

Pythonのパッケージ化/モジュール化についての説をしました。

機能ごとにファイルを分けて整理すると利便性が増しますね。

↓以下がPython初学者のためのお勧めの参考書です。

本記事の内容に関して詳しくは↓こちらの参考書に記載があります。

独習Python

独習Python

山田 祥寛
2,970円(09/18 13:49時点)
発売日: 2020/06/22
Amazonの情報を掲載しています

【プロフィール】

カマキリ
(^^)

大学の専攻は物性理論で、Fortranを使って数値計算をしていました。
CAEを用いた流体解析は興味がありOpenFOAMを使って勉強しています。

プロフィール記事はこちら

 

大学学部レベルの物理の解説をします 大学初学者で物理にお困りの方にわかりやすく解説します。

このブログでは主に大学以上の物理を勉強して記事にわかりやすくまとめていきます。

  • ・解析力学
  • ・流体力学
  • ・熱力学
  • ・量子統計
  • ・CAE解析(流体解析)
  • note
    noteで内容は主に「プログラミング言語」の勉強の進捗を日々書いています。また、「現在勉強中の内容」「日々思ったこと」も日記代わりに書き記しています。
  • youtube
    youtubeではオープンソースの流体解析、構造解析、1DCAEの操作方法などを動画にしています。
    (音声はありません_(._.)_)
  • Qiita
    Qiitaではプログラミング言語の基本的な内容をまとめています。