Pythonモジュール:コードを整理して明確性と再利用性を高める
モジュールとは
モジュールを使用すると、Pythonコードを論理的に整理できます。関連するコードをモジュールにグループ化することで、コードの理解と利用が容易になります。モジュールは、任意の名前の属性を持ち、それらをバインドおよび参照できるPythonオブジェクトです。
簡単に言うと、モジュールはPythonコードで構成されるファイルです。モジュールには関数、クラス、変数を定義でき、実行可能なコードを含めることもできます。
例
anameという名前のモジュールのPythonコードは、通常aname.pyというファイルに保存されます。以下は、support.pyというシンプルなモジュールの例です。
def print_func(par):
print("Hello : ", par)
return
import文
別のPythonソースファイルでimport文を実行することで、任意のPythonソースファイルをモジュールとして使用できます。import文の構文は以下の通りです。
import module1[, module2[,... moduleN]]
インタープリタがimport文に遭遇すると、モジュールが検索パスに存在する場合にそれをインポートします。検索パスとは、インタープリタがモジュールをインポートする前に検索するディレクトリのリストです。例えば、support.pyモジュールをインポートするには、スクリプトの先頭に以下のコマンドを記述します。
#!/usr/bin/python
# モジュール support をインポート
import support
# モジュールで定義された関数を以下のように呼び出せます
support.print_func("Zara")
上記コードを実行すると、以下の結果が出力されます。
Hello : Zara
モジュールは、インポートされる回数に関わらず一度だけ読み込まれます。これにより、複数回インポートされた場合でもモジュールの実行が繰り返し行われることを防止します。
from...import文
Pythonのfrom文を使用すると、モジュールから特定の属性を現在の名前空間にインポートできます。from...importの構文は以下の通りです。
from modname import name1[, name2[, ... nameN]]
例えば、fibモジュールからfibonacci関数をインポートするには、以下の文を使用します。
from fib import fibonacci
この文はfibモジュール全体を現在の名前空間にインポートするのではなく、fibモジュールからfibonacciという項目だけをインポート側のグローバルシンボルテーブルに導入します。
from...import *文
以下のimport文を使用して、モジュールからすべての名前を現在の名前空間にインポートすることも可能です。
from modname import *
これにより、モジュールからすべての項目を現在の名前空間に簡単にインポートできますが、この文は控えめに使用すべきです。
モジュールの検索
モジュールをインポートすると、Pythonインタープリタは以下の順序でモジュールを検索します。
- カレントディレクトリ
- モジュールが見つからない場合、Pythonはシェル変数
PYTHONPATHの各ディレクトリを検索 - それでも見つからない場合、Pythonはデフォルトパスをチェック。UNIXでは通常
/usr/local/lib/python/
モジュール検索パスは、システムモジュールsysのsys.path変数に格納されています。sys.pathには、カレントディレクトリ、PYTHONPATH、インストール依存のデフォルトパスが含まれます。
PYTHONPATH変数
PYTHONPATHは、ディレクトリのリストで構成される環境変数です。PYTHONPATHの構文は、シェル変数PATHと同じです。
Windowsシステムでの典型的なPYTHONPATHの例:
set PYTHONPATH = c:\python20\lib;
UNIXシステムでの典型的なPYTHONPATHの例:
set PYTHONPATH = /usr/local/lib/python
名前空間とスコーピング
変数はオブジェクトにマッピングされる名前(識別子)です。名前空間とは、変数名(キー)とそれに対応するオブジェクト(値)の辞書です。
Python文は、ローカル名前空間とグローバル名前空間の変数にアクセスできます。ローカル変数とグローバル変数が同じ名前を持つ場合、ローカル変数がグローバル変数をシャドウします。
各関数は独自のローカル名前空間を持ちます。クラスメソッドも通常の関数と同じスコーピングルールに従います。
Pythonは、変数がローカルかグローバルかについて推測を行います。関数内で値が代入されている変数はローカルと見なされます。
したがって、関数内でグローバル変数に値を代入するには、まずglobal文を使用する必要があります。
global VarName文は、PythonにVarNameがグローバル変数であることを伝えます。Pythonはその変数についてローカル名前空間の検索を停止します。
例えば、グローバル名前空間にMoney変数を定義し、関数Money内でそれに値を代入すると、PythonはMoneyをローカル変数と見なします。しかし、ローカル変数Moneyに値を設定する前にその値にアクセスしようとすると、UnboundLocalErrorが発生します。global文のコメントを外すと問題が解決します。
#!/usr/bin/python
Money = 2000
def AddMoney():
# 以下の行のコメントを外してコードを修正:
# global Money
Money = Money + 1
print(Money)
AddMoney()
print(Money)
dir()関数
組み込み関数dir()は、モジュールで定義されている名前を含むソート済みの文字列リストを返します。
このリストには、モジュールで定義されているすべてのモジュール、変数、関数の名前が含まれます。以下は簡単な例です。
#!/usr/bin/python
# 組み込みモジュール math をインポート
import math
content = dir(math)
print(content)
上記コードを実行すると、以下のような結果が出力されます。
['__doc__', '__file__', '__name__', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh']
ここで、特殊な文字列変数__name__はモジュール名、__file__はモジュールが読み込まれたファイル名です。
globals()とlocals()関数
globals()とlocals()関数は、呼び出し場所に応じてグローバルおよびローカル名前空間の名前を返すために使用できます。
locals()が関数内から呼び出された場合、その関数からローカルにアクセスできるすべての名前を返します。globals()が関数内から呼び出された場合、その関数からグローバルにアクセスできるすべての名前を返します。
両関数の戻り値の型は辞書です。したがって、keys()関数を使用して名前を抽出できます。
reload()関数
モジュールがスクリプトにインポートされると、モジュールのトップレベル部分のコードは一度だけ実行されます。
したがって、モジュールのトップレベルコードを再実行したい場合は、reload()関数を使用できます。reload()関数は、以前にインポートされたモジュールを再度インポートします。構文は以下の通りです。
reload(module_name)
ここで、module_nameは再読み込みしたいモジュールの名前であり、モジュール名を含む文字列ではありません。例えば、helloモジュールを再読み込みするには以下のようにします。
reload(hello)
Pythonのパッケージ
パッケージは、モジュール、サブパッケージ、サブサブパッケージなどで構成される単一のPythonアプリケーション環境を定義する階層的なファイルディレクトリ構造です。
PhoneディレクトリにPots.pyというファイルがあり、以下のソースコードが含まれているとします。
#!/usr/bin/python
def Pots():
print("I'm Pots Phone")
同様に、同じ名前の異なる関数を持つ2つのファイルがあります。
- Phone/Isdn.py ファイルに
Isdn()関数 - Phone/G3.py ファイルに
G3()関数
次に、Phoneディレクトリに__init__.pyファイルを作成します。
- Phone/__init__.py
Phoneをインポートしたときにすべての関数を利用できるようにするには、__init__.pyに明示的なimport文を記述します。
from Pots import Pots
from Isdn import Isdn
from G3 import G3
これらの行を__init__.pyに追加すると、Phoneパッケージをインポートしたときにこれらすべてのクラスが利用可能になります。
#!/usr/bin/python
# Phoneパッケージをインポート
import Phone
Phone.Pots()
Phone.Isdn()
Phone.G3()
上記コードを実行すると、以下の結果が出力されます。
I'm Pots Phone
I'm 3G Phone
I'm ISDN Phone
上記の例では各ファイルに単一の関数を配置しましたが、ファイルには複数の関数を配置できます。また、それらのファイルに異なるPythonクラスを定義し、それらのクラスからパッケージを作成することもできます。
Python
- Python データ型マスター: 実践ガイド
- Python I/Oとモジュールインポート完全マスター: 実践ガイド
- Python 演算子完全マスター: 包括的ガイド
- Python 関数引数完全マスター: 位置引数・キーワード引数・デフォルト引数
- Python モジュール: 作成・インポート・高度な活用
- Python辞書完全ガイド:作成、操作、高度なテクニック
- Pythonイテレータ完全ガイド:仕組みと自作方法
- Pythonクロージャ解説:ネスト関数が変数を捕捉する仕組み
- Python datetimeマスター:日付・時刻・タイムゾーン実践ガイド
- Pythonのtimeモジュールをマスター:関数、構造体、実践例
- Pythonのtime.sleep()をマスター:ベストプラクティス、マルチスレッド、実例