2017年12月27日水曜日

[Python] モジュール

モジュールのインポートは過去の投稿(例えば前回)でも使用しています.
前回の投稿のモジュールのインポートは,以下の部分で行なっています.
>>> import datetime

モジュールは,関数,クラス,定数などを集めたものです.ちなみに,上記の datetime モジュールは日付や時間に関する操作をまとめたモジュールです.上記のようにモジュールをインポートすると,そのモジュール内の関数,クラスを使うことができます.
以下の例のように,datetime モジュールをインポートして,datetimeモジュール内のdate クラスを使用します.
>>> import datetime
>>> d = datetime.date(2017, 12, 27) # Creating a data object
>>> d
datetime.date(2017, 12, 27)

同じクラスを多用する場合は,毎回 datetime.data として参照するのが面倒と感じる場合は,以下のように from ... import ... 構文を使用することもできます.
>>> from datetime import date
>>> d = date(2017, 12, 27)
>>> d
datetime.date(2017, 12, 27)
この例のように,インポートしたいクラス(関数,定数も同様)を指定してインポートすると,それ以降はモジュール名を指定しなくてもそのクラス(関数,定数)を使用することができるようになります.

モジュール内の全てをインポートするには以下のようにすることもできますが,複数のモジュールをインポートした際には,名前の衝突に気づかないことがあります.
>>> from datetime import *
>>> d = date(2017, 12, 27)
>>> d
datetime.date(2017, 12, 27)

上記の理由で,全てをインポートすることは推奨されていないので,以下のように長いモジュール名を使わないようにするために,import ... as ... 構文を使用することができます.
>>> import datetime as dt
>>> d = dt.date(2017, 12, 27)
>>> d
datetime.date(2017, 12, 27)
1行目でdatetimeモジュールをdtとしてインポートして,それ以降はdt はdatetime モジュールを指します.この昨日は,名前の衝突を避けてコードを短くできるというメリットがありますが,乱用すると可読性が低下するデメリットがあります.

モジュールの作成
独自にモジュールを作成する場合は,特に明示的に宣言する必要はありません..pyファイルにクラス,関数,および定数などを記述すると,自動的にモジュールとして扱うことができるようになります.以下はその例です.

まずは,以下のコードを作成してmod1.pyという名前で保存します.
def hello():
    return "Hello!"

続いて,REPLでPythonを起動して以下のようにmod1をインポートして実行すると以下のようになります.
>>> import mod1
>>> print(mod1.hello())
Hello!

また,以下のコードを作成して,ex.pyという名前で(mod1.pyと同じディレクトリに)保存します.
import mod1

print(mod1.hello())

そして,以下のようにターミナルからex.pyを実行すると以下のように表示されます.
$ python3 ex.py
Hello!
ex.pyでは,モジュール mod1 をインポートしています.この命令によって,同じディレクトリにあるmod1.pyが読み込まれます.この例のように,モジュールをインポートした際には同じディレクトリ内のファイルが優先的に探索されます(先述の datetime のような標準モジュールは,Pythonのシステム内に組み込まれており,システム内の特定のディレクトリから探索されてインポートされます).
なお,モジュールをインポートする時に,グローバル領域にある文は実行される(下のex2.pyの例で確認できます)ことに注意が必要です.

以下のコードをmod2.pyという名前で保存します.
def meow():
    print("Meow!")

print("I am imported"# "print" is in the global area

mod2.pyと同じディレクトリにex2.pyという名前で以下のコードを保存します.
import mod2

print("Bowwow!")

mod2.meow()

ここで,ex2.pyを実行すると,mod2.pyのグローバル領域にあるprint関数がインポートした際(最初)に実行されていることがわかります.
$ python3 ex2.py
I am imported
Bowwow!
Meow!

インポート時に何らかの副作用が起こるのは,多くの場合は望まれる動作でないことがほとんどなので,注意が必要です.

同一のファイルをモジュールと実行スクリプトの両方で利用して,インポート時には(上記のような)副作用が生じないようにするときの例を示します.
以下のコードをmod3.pyという名前で保存します.
def meow():
    print("Meow!")

def main():
    print("Entering main")
    meow()


if __name__ == "__main__"

    main()

以下のコードをex3.pyという名前で保存します.
import mod3


mod3.meow()

ex3.pyとmod3.pyを順番に実行してみます.
$ python3 ex3.py
Meow!

$ python3 mod3.py
Entering main
Meow!
mod3.py のif文は,もしこのファイルが直接実行された(モジュールとしてインポートされていない)場合を表すif文です.なので,直接実行された時だけmain関数が呼ばれることになります.

上記の例では,ex3.pyが実行された場合はmod3のモジュールがインポートされているので,meow関数のみが呼ばれて実行されています.mod3.pyを実行した場合には,main関数が呼ばれて実行されていることが確認できます.

上記のコードや内容は機械学習のエッセンスを参考にしています.

0 件のコメント :

コメントを投稿