はじめに
この実験では、Python モジュールの基本を学びます。モジュールは、関数、クラス、変数の定義を含む Python ファイルで、他の Python プログラムで使用することができます。モジュールは、コードを論理的な単位に整理し、再利用性を高めるのに役立ちます。
この実験の終了時には、独自のモジュールを作成する方法、様々な方法でモジュールをインポートする方法、およびコードに影響を与える重要なモジュール読み込み動作を理解するようになります。
This tutorial is from open-source community. Access the source code
💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください
この実験では、Python モジュールの基本を学びます。モジュールは、関数、クラス、変数の定義を含む Python ファイルで、他の Python プログラムで使用することができます。モジュールは、コードを論理的な単位に整理し、再利用性を高めるのに役立ちます。
この実験の終了時には、独自のモジュールを作成する方法、様々な方法でモジュールをインポートする方法、およびコードに影響を与える重要なモジュール読み込み動作を理解するようになります。
Python モジュールの旅に、シンプルなモジュールを作成することから始めましょう。Python では、モジュールは本質的に .py
拡張子を持つ Python コードを含むファイルです。関連する関数、クラス、変数をまとめるコンテナと考えてください。これにより、特にプロジェクトが大規模になるにつれて、コードが整理され、管理しやすくなります。
まず、WebIDE を開きます。開いたら、新しいファイルを作成する必要があります。これを行うには、メニューバーの「File」をクリックし、「New File」を選択します。この新しいファイルを simplemod.py
と名付け、/home/labex/project
ディレクトリに保存します。このディレクトリは、この実験に関連するすべてのファイルを保管する場所です。
次に、新しく作成した simplemod.py
ファイルにいくつかのコードを追加しましょう。以下のコードは、Python モジュールによく見られるいくつかの基本要素を定義しています。
## simplemod.py
x = 42 ## グローバル変数
## シンプルな関数
def foo():
print('x is', x)
## シンプルなクラス
class Spam:
def yow(self):
print('Yow!')
## スクリプト文
print('Loaded simplemod')
このコードでは:
x = 42
は、x
という名前のグローバル変数を作成し、それに値 42
を割り当てます。グローバル変数は、モジュール内のどこからでもアクセスできます。foo()
関数は、グローバル変数 x
の値を出力するように定義されています。関数は、特定のタスクを実行する再利用可能なコードブロックです。Spam
クラスは、オブジェクトを作成するためのブループリントです。yow()
という名前のメソッドを持ち、単に文字列 'Yow!' を出力します。メソッドは、クラスに属する関数です。print('Loaded simplemod')
文はスクリプト文です。モジュールが読み込まれるとすぐに実行され、モジュールが正常に読み込まれたことを確認するのに役立ちます。Ctrl+S
を押すか、メニューから「File」>「Save」を選択することで行えます。ファイルを保存することで、行ったすべての変更が保存されます。このモジュールが含む内容をもう少し詳しく見てみましょう:
42
のグローバル変数 x
。この変数はモジュール全体で使用でき、正しくインポートすれば他のモジュールからもアクセスできます。x
の値を出力する関数 foo()
。関数は、同じコードを何度も書かずに繰り返しタスクを実行するのに便利です。yow()
を持つクラス Spam
。クラスとメソッドは、オブジェクト指向プログラミングの基本的な概念で、複雑なデータ構造と振る舞いを作成することができます。print
文。この文は、モジュールが Python 環境に正常に読み込まれたことを視覚的に示す役割を果たします。一番下の print
文は、モジュールがいつ読み込まれるかを観察するのに役立ちます。これは、デバッグや Python でのモジュールの動作を理解するために重要です。
モジュールを作成したので、次はそれをインポートしてそのコンポーネントを使用する方法を理解する時です。Python では、モジュールは Python の定義と文を含むファイルです。モジュールをインポートすると、その中で定義されたすべての関数、クラス、変数にアクセスできるようになります。これにより、コードを再利用し、プログラムをより効果的に整理することができます。
まず、WebIDE で新しいターミナルを開く必要があります。このターミナルは、Python コマンドを実行できる作業スペースとして機能します。新しいターミナルを開くには、「Terminal」>「New Terminal」をクリックします。
ターミナルが開いたら、Python インタープリタを起動する必要があります。Python インタープリタは、Python コードを読み取って実行するプログラムです。起動するには、ターミナルに以下のコマンドを入力して Enter キーを押します。
python3
import
文を使用してモジュールを現在のプログラムに取り込みます。Python インタープリタに以下のコマンドを入力します。>>> import simplemod
Loaded simplemod
出力に「Loaded simplemod」が表示されることに気づくでしょう。これは、simplemod
モジュールの print
文がモジュールが読み込まれたときに実行されるためです。Python がモジュールをインポートすると、そのモジュール内のすべてのトップレベルのコード、print
文を含め、実行されます。
simplemod
モジュールのさまざまなコンポーネントにアクセスする方法の例を以下に示します。>>> simplemod.x
42
>>> simplemod.foo()
x is 42
>>> spam_instance = simplemod.Spam()
>>> spam_instance.yow()
Yow!
最初の行では、simplemod
モジュールで定義された変数 x
にアクセスしています。2 行目では、simplemod
モジュールの関数 foo
を呼び出しています。3 行目と 4 行目では、simplemod
モジュールで定義された Spam
クラスのインスタンスを作成し、そのメソッド yow
を呼び出しています。
ImportError
に遭遇することがあります。このエラーは、Python がインポートしようとしているモジュールを見つけることができないときに発生します。Python がモジュールを探している場所を調べるには、sys.path
変数を調べることができます。sys.path
変数は、Python がモジュールを探すときに検索するディレクトリのリストです。Python インタープリタに以下のコマンドを入力します。>>> import sys
>>> sys.path
['', '/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/usr/local/lib/python3.10/dist-packages', '/usr/lib/python3/dist-packages']
リストの最初の要素(空文字列)は、現在の作業ディレクトリを表しています。ここが Python が simplemod.py
ファイルを探す場所です。モジュールが sys.path
にリストされているディレクトリのいずれにもない場合、Python はそれを見つけることができず、ImportError
が発生します。simplemod.py
ファイルが現在の作業ディレクトリまたは sys.path
の他のディレクトリのいずれかにあることを確認してください。
Python では、モジュールの読み込み方法にいくつか興味深い特性があります。このステップでは、これらの動作を調べて、Python がモジュールの読み込みをどのように管理しているかを理解しましょう。
>>> import simplemod
今回は「Loaded simplemod」という出力が表示されないことに注意してください。これは、Python はインタープリタセッションごとにモジュールを一度だけ読み込むからです。その後の import
文はモジュールを再読み込みしません。Python はすでにモジュールを読み込んだことを記憶しているので、再度読み込むプロセスを経ません。
>>> simplemod.x
42
>>> simplemod.x = 13
>>> simplemod.x
13
>>> simplemod.foo()
x is 13
ここでは、まず simplemod
モジュール内の変数 x
の値を確認します。最初は 42
です。次にその値を 13
に変更し、変更が反映されていることを確認します。モジュール内の foo
関数を呼び出すと、x
の新しい値が反映されます。
>>> import simplemod
>>> simplemod.x
13
importlib.reload()
関数を使用する必要があります。時には、モジュールのコードに変更を加え、それらの変更を即座に反映させたいことがあります。importlib.reload()
関数を使用すると、それが可能になります。>>> import importlib
>>> importlib.reload(simplemod)
Loaded simplemod
<module 'simplemod' from 'simplemod.py'>
>>> simplemod.x
42
>>> simplemod.foo()
x is 42
モジュールが再読み込みされ、x
の値が 42
にリセットされました。これは、モジュールがソースコードから再度読み込まれ、すべての変数が元の状態に初期化されたことを示しています。
sys.modules
辞書に記録します。この辞書は、現在のインタープリタセッション中に読み込まれたすべてのモジュールに関する情報を格納するレジストリのようなものです。>>> 'simplemod' in sys.modules
True
>>> sys.modules['simplemod']
<module 'simplemod' from 'simplemod.py'>
モジュール名が sys.modules
辞書に含まれているかどうかを確認することで、そのモジュールが読み込まれているかどうかを確認できます。また、モジュール名をキーとして辞書にアクセスすることで、そのモジュールに関する情報を取得できます。
sys.modules
辞書からモジュールを削除すると、Python はそのモジュールをすでに読み込んだことを忘れます。したがって、次にそのモジュールをインポートしようとすると、Python はソースコードから再度読み込みます。>>> del sys.modules['simplemod']
>>> import simplemod
Loaded simplemod
>>> simplemod.x
42
モジュールは sys.modules
から削除されたため、再度読み込まれました。これは、モジュールのコードの最新バージョンを使用することを保証する別の方法です。
from module import
構文の使用Python では、モジュールからコンポーネントをインポートする方法は様々あります。そのうちの 1 つが from module import
構文で、このセクションではこれについて説明します。
モジュールからコンポーネントをインポートする際には、新しい状態から始めることが良いアイデアです。これにより、以前の操作で残っている変数や設定が現在の実験に影響を与えることがなくなります。
>>> exit()
このコマンドは現在の Python インタープリタセッションを終了します。終了した後、新しいセッションを開始して新しい環境を確保します。
python3
この bash コマンドは新しい Python 3 インタープリタセッションを開始します。これで新しい Python 環境ができたので、モジュールからコンポーネントをインポートし始めることができます。
from module import
構文を使用してモジュールから特定のコンポーネントをインポートする:>>> from simplemod import foo
Loaded simplemod
>>> foo()
x is 42
ここでは、from simplemod import foo
文を使用して、simplemod
モジュールから foo
関数のみをインポートしています。foo
関数のみを要求したにもかかわらず、simplemod
モジュール全体が読み込まれたことに注意してください。これは「Loaded simplemod」という出力で示されています。これは、Python が foo
関数にアクセスするためにモジュール全体を読み込む必要があるからです。
from module import
を使用すると、モジュール自体にアクセスできない:>>> simplemod.foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'simplemod' is not defined
from module import
構文を使用すると、指定されたコンポーネントのみが直接名前空間に取り込まれます。モジュール名自体はインポートされません。したがって、simplemod.foo()
にアクセスしようとすると、Python は simplemod
を認識できず、そのようにインポートされていないためエラーが発生します。
>>> from simplemod import x, foo
>>> x
42
>>> foo()
x is 42
from module import
構文を使用すると、1 つの文でモジュールから複数のコンポーネントをインポートすることができます。ここでは、simplemod
モジュールから変数 x
と関数 foo
の両方をインポートしています。インポート後、これらのコンポーネントにコード内で直接アクセスすることができます。
>>> x = 13 ## ローカル変数 x を変更する
>>> x
13
>>> foo()
x is 42 ## 関数はまだモジュールの x を使用しており、ローカルの x ではない
モジュールから変数をインポートすると、実質的にローカル名前空間内で同じオブジェクトへの新しい参照が作成されます。したがって、ローカル変数 x
を 13
に変更しても、simplemod
モジュール内の x
変数には影響しません。foo()
関数は依然としてモジュールの x
変数(42
)を参照しています。この概念を理解することは、コードでの混乱を避けるために重要です。
モジュールの再読み込みは Python で便利な機能ですが、特にクラスを扱う際にはいくつかの制限があります。このセクションでは、これらの制限を段階的に調べていきます。これらの制限を理解することは、開発環境と本番環境の両方において重要です。
exit()
コマンドを使用します。その後、ターミナルで python3
コマンドを使用して新しい Python インタープリタセッションを開始します。>>> exit()
python3
Spam
クラスのインスタンスを作成する:simplemod
モジュールをインポートします。モジュールをインポートすることで、そのモジュールで定義されたクラス、関数、変数を使用することができます。モジュールをインポートした後、Spam
クラスのインスタンスを作成し、その yow()
メソッドを呼び出します。これにより、クラスの初期の動作を確認することができます。>>> import simplemod
Loaded simplemod
>>> s = simplemod.Spam()
>>> s.yow()
Yow!
Spam
クラスを変更しましょう。Python インタープリタを終了する:simplemod
モジュール内の Spam
クラスに変更を加えます。その前に、Python インタープリタを終了する必要があります。これは、モジュールのソースコードに変更を加え、それがクラスの動作にどのように影響するかを確認するためです。>>> exit()
simplemod.py
ファイルを開き、Spam
クラスを変更する:simplemod.py
ファイルを開きます。ここに simplemod
モジュールのソースコードがあります。Spam
クラスの yow()
メソッドを変更して、別のメッセージを出力するようにします。この変更により、モジュールを再読み込みした後のクラスの動作の変化を観察することができます。## simplemod.py
## ... (ファイルの残りの部分は変更しないでおく)
class Spam:
def yow(self):
print('More Yow!') ## 'Yow!' から変更
simplemod.py
ファイルに変更を加えた後、保存します。その後、ターミナルに戻り、新しい Python インタープリタセッションを開始します。再度 simplemod
モジュールをインポートし、Spam
クラスの新しいインスタンスを作成します。新しいインスタンスの yow()
メソッドを呼び出して、更新された動作を確認します。python3
>>> import simplemod
Loaded simplemod
>>> t = simplemod.Spam()
>>> t.yow()
More Yow!
importlib.reload()
関数を使用します。この関数を使用すると、以前にインポートしたモジュールを再読み込みすることができます。モジュールを再読み込みした後、Spam
クラスに加えた変更が反映されているかを確認します。>>> import importlib
>>> importlib.reload(simplemod)
Loaded simplemod
<module 'simplemod' from 'simplemod.py'>
simplemod.py
ファイル内の Spam
クラスに別の変更を加えます。その後、Spam
クラスの古いインスタンスと新しいインスタンスの両方をテストして、それらの動作を確認します。>>> exit()
simplemod.py
ファイルを更新する:simplemod.py
ファイルを開き、Spam
クラスの yow()
メソッドを変更して、別のメッセージを出力するようにします。この変更により、モジュール再読み込みの制限をさらに理解することができます。## simplemod.py
## ... (ファイルの残りの部分は変更しないでおく)
class Spam:
def yow(self):
print('Even More Yow!') ## 再度変更
simplemod.py
ファイルの変更を保存し、ターミナルに戻ります。新しい Python インタープリタセッションを開始し、simplemod
モジュールをインポートし、Spam
クラスの新しいインスタンスを作成します。新しいインスタンスの yow()
メソッドを呼び出して、更新された動作を確認します。python3
>>> import simplemod
Loaded simplemod
>>> s = simplemod.Spam()
>>> s.yow()
Even More Yow!
>>> ## Python を閉じずに終了し、ファイルを編集する
simplemod.py
を開き、変更する:simplemod.py
ファイルを開き、Spam
クラスの yow()
メソッドに別の変更を加えます。これにより、モジュールを再読み込みした後の既存のインスタンスと新しいインスタンスの動作の変化を確認することができます。## simplemod.py
## ... (ファイルの残りの部分は変更しないでおく)
class Spam:
def yow(self):
print('Super Yow!') ## さらに変更
simplemod.py
ファイルの変更を保存し、Python インタープリタに戻ります。importlib.reload()
関数を使用して simplemod
モジュールを再読み込みします。その後、Spam
クラスの古いインスタンスと新しいインスタンスの両方をテストして、それらの動作を確認します。>>> import importlib
>>> importlib.reload(simplemod)
Loaded simplemod
<module 'simplemod' from 'simplemod.py'>
>>> ## 古いインスタンスを試す
>>> s.yow()
Even More Yow! ## まだ古い実装を使用している
>>> ## 新しいインスタンスを作成する
>>> t = simplemod.Spam()
>>> t.yow()
Super Yow! ## 新しい実装を使用している
古いインスタンス s
はまだ古い実装を使用しているのに対し、新しいインスタンス t
は新しい実装を使用していることに注意してください。これは、モジュールを再読み込みしても既存のクラスインスタンスは更新されないためです。クラスインスタンスが作成されると、その時点のクラスオブジェクトへの参照が保存されます。モジュールを再読み込むと新しいクラスオブジェクトが作成されますが、既存のインスタンスは依然として古いクラスオブジェクトを参照しています。
isinstance()
関数を使用することで、モジュール再読み込みの制限をさらに観察することができます。この関数は、オブジェクトが特定のクラスのインスタンスであるかどうかを確認します。モジュールを再読み込みした後、古いインスタンス s
は新しい simplemod.Spam
クラスのインスタンスとは見なされなくなり、新しいインスタンス t
は見なされることがわかります。>>> isinstance(s, simplemod.Spam)
False
>>> isinstance(t, simplemod.Spam)
True
これは、再読み込み後、simplemod.Spam
が s
を作成するために使用されたクラスオブジェクトとは異なるクラスオブジェクトを参照していることを示しています。
これらの制限により、モジュール再読み込みは主に開発とデバッグに有用ですが、本番コードでの使用は推奨されません。本番環境では、クラスのすべてのインスタンスが同じ最新の実装を使用することを確保することが重要です。モジュール再読み込みは一貫性のない動作を引き起こす可能性があり、デバッグや保守が困難になります。
この実験では、Python のモジュールを扱う基本的な方法を学びました。変数、関数、クラスを含む .py
ファイルとして Python モジュールを作成する方法や、import
文を使用してモジュールをインポートする方法を学びました。また、Python がインタープリタセッションごとにモジュールを 1 回だけ読み込むこと、および importlib.reload()
を使用して強制的に再読み込みできることも理解しました。
さらに、読み込まれたモジュールを追跡するための sys.modules
辞書を調べ、from module import
構文を使用して特定のコンポーネントをインポートし、特にクラスに関するモジュール再読み込みの制限を理解しました。これらの概念は、Python コードを再利用可能なコンポーネントに整理するための基礎であり、大規模なアプリケーションにおけるコード構造の維持と再利用性の促進に不可欠です。