Pythonモジュール
これまでの章では、基本的に Python インタープリターを使用してプログラミングを行ってきましたが、Python インタープリターを終了してから再度開始すると、定義したメソッドと変数はすべて消えてしまいます。
この目的のために、Python では、一部のスクリプトまたは対話型インタープリター インスタンスで使用できるように、これらの定義をファイルに保存する方法が提供されており、このファイルはモジュールと呼ばれます。
モジュールは、定義したすべての関数と変数を含むファイルであり、その拡張子は .py です。モジュールを他のプログラムでインポートして、モジュール内の関数などを使用することができます。これも Python 標準ライブラリを使用して行われます。
以下は、Python 標準ライブラリのモジュールを使用した例です。
#!/usr/bin/python3
# 文件名: using_sys.py
import sys
print('命令行参数如下:')
for i in sys.argv:
print(i)
print('\n\nPython 路径为:', sys.path, '\n')
実行結果は以下のようになります。
$ python using_sys.py パラメータ 1 パラメータ 2
コマンド ライン パラメータは次のとおりです。
using_sys.py
パラメータ 1
パラメータ 2
Python パスは次のとおりです: ['/root', '/usr/lib/python3.4', '/usr/ lib/python3.4/plat-x86_64-linux-gnu'、'/usr/lib/python3.4/lib-dynload'、'/usr/local/lib/python3.4/dist-packages'、'/usr /lib/python3 /dist-packages']
- import sys は、Python 標準ライブラリの sys.py モジュールを導入します。これは、モジュールを導入する方法です。
- sys.argv は、コマンド ライン引数を含むリストです。
- sys.path には、Python インタープリターが必要なモジュールを自動的に検索するパスのリストが含まれています。
インポートステートメント
Python ソース ファイルを使用する場合は、別のソース ファイルで import ステートメントを実行するだけです。構文は次のとおりです。
モジュール1、モジュール2、…モジュールNをインポート
ここで、「module」はインポートする Python ソース ファイルの名前です (.py 接尾辞は必要ありません)。インポート後、呼び出しの前にモジュール名を付けることで、このモジュール内の任意の関数またはクラスを使用できます。
インタプリタが import ステートメントに遭遇すると、モジュールが現在の検索パス内にあればインポートされます。
検索パスは、インタープリタが最初に検索するすべてのディレクトリのリストです。サポート モジュールをインポートする場合は、スクリプトの先頭にコマンドを置く必要があります。
#!/usr/bin/python3
# Filename: support.py
def print_func( par ):
print ("Hello : ", par)
return
test.py はサポート モジュールを導入します。
#!/usr/bin/python3
# Filename: test.py
# 导入模块
import support
# 现在可以调用模块里包含的函数了
support.print_func("Tarzan")
上記の例の出力は次のとおりです。
C:\Users\Lenovo\Desktop>python test.py
こんにちは : Tarzan
インポートを何回実行しても、モジュールは 1 回だけインポートされます。これにより、インポートされたモジュールが何度も実行されるのを防ぎます。
import ステートメントを使用する場合、Python インタープリターは対応するファイルをどのように見つけますか?
これには、一連のディレクトリ名で構成される Python の検索パスが関係し、Python インタープリターはこれらのディレクトリからインポートされたモジュールを順番に検索します。
これは環境変数によく似ており、実際、環境変数を定義することで検索パスも決定できます。
検索パスは、Python がコンパイルまたはインストールされるときに決定され、新しいライブラリをインストールするときにも変更する必要があります。検索パスは、sys モジュールのパス変数に保存されます。簡単な実験を行うには、対話型インタープリターに次のコードを入力します。
>>> import sys
>>> sys.path
['', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages']
>>>
sys.path の出力はリストであり、その最初の項目は現在のディレクトリを表す空の文字列 '' です (スクリプトから出力される場合は、どのディレクトリであるかがより明確にわかります)。 Python インタープリターを実行するときのディレクトリ (スクリプトの場合、これは実行されるスクリプトが配置されているディレクトリです)。
したがって、私のように、カレントディレクトリにインポートするモジュールと同じ名前のファイルがある場合、インポートするモジュールはブロックされます。
検索パスの概念を理解した後、スクリプト内の sys.path を変更して、検索パスにないいくつかのモジュールを導入できます。
ここで、インタープリタの現在のディレクトリまたは sys.path 内のディレクトリに fibo.py ファイルを作成します。コードは次のとおりです。
# 斐波那契(fibonacci)数列模块
def fib(n): # 定义到 n 的斐波那契数列
a, b = 0, 1
while b < n:
print(b, end=' ')
a, b = b, a+b
print()
def fib2(n): # 返回到 n 的斐波那契数列
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
return result
次に、Python インタープリターを開始し、次のコマンドを使用してこのモジュールをインポートします。
import fibo
これは、fibo で直接定義された関数名を現在のシンボル テーブルに書き込むのではなく、モジュール fibo の名前のみをそこに書き込みます。
関数にはモジュール名を使用してアクセスできます。
>>>fibo.fib(1000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'
関数を頻繁に使用する予定がある場合は、その関数にローカル名を付けることができます。
>>> fib = fibo.fib
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
from …インポートステートメント
Python の from ステートメントを使用すると、指定した部分をモジュールから現在の名前空間にインポートできます。構文は次のとおりです。
module_name から name1、name2、… nameN をインポート
たとえば、モジュール fibo の fib 関数をインポートするには、次のステートメントを使用します。
>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
この宣言は、fibo モジュール全体を現在の名前空間にインポートするのではなく、fibo に fib 関数を導入するだけです。
from … import * ステートメント
次の宣言を使用して、モジュールの内容全体を現在の名前空間にインポートすることもできます。
from module_name import *
これにより、モジュール内のすべてのプロジェクトを簡単にインポートできます。ただし、このステートメントは乱用すべきではありません。
>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
注: これにより、単一のアンダースコア (_) で始まる名前を除くすべての名前がインポートされます。他のソースから名前を導入すると既存の定義が上書きされる可能性があるため、ほとんどの場合、Python プログラマはこの方法を使用しません。
モジュールを詳しく見る
メソッド定義に加えて、モジュールには実行可能コードを含めることもできます。これらのコードは通常、このモジュールを初期化するために使用されます。このコードは、最初にインポートされたときにのみ実行されます。
各モジュールには独自の独立したシンボル テーブルがあり、モジュール内のすべての関数のグローバル シンボル テーブルとして使用されます。
したがって、モジュール作成者は、他のユーザーのグローバル変数を混乱させることを心配することなく、モジュール内でこれらのグローバル変数を安全に使用できます。
一方、何をしているのかを本当に理解している場合は、module_name.itemnameなどの表記を使用してモジュール内の関数にアクセスすることもできます。
モジュールは他のモジュールをインポートできます。モジュールをインポートするには、モジュール (またはスクリプトなど) の先頭で import を使用します。もちろん、これは単なる慣例であり、要件ではありません。インポートされたモジュールの名前は、現在動作しているモジュールのシンボル テーブルに配置されます。
__name__ 属性
モジュールが別のプログラムによって初めて導入されると、そのメイン プログラムが実行されます。モジュールのインポート時にモジュール内の特定のプログラム ブロックを実行したくない場合は、__name__ 属性を使用して、モジュール自体の実行時にのみプログラム ブロックが実行されるようにすることができます。
#!/usr/bin/python3
# Filename: using_name.py
if __name__ == '__main__':
print('程序自身在运行')
else:
print('我来自另一模块')
実行中の出力は次のとおりです。
C:\Users\Lenovo\Desktop>python using_name.py
プログラム自体が実行されています
C:\Users\Lenovo\Desktop>python
Python 3.11.4 (tags/v3.11.4:d2340ef, Jun 7 2023, 05:45:37) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import using_name
我来自另一模块
>>>
説明:
- 各モジュールには _ name__ 属性があり、その値が '_ main ' の場合はモジュール自体が実行中であることを示し、それ以外の場合はインポートされます。
- _ name _ と _ main _の下に二重アンダースコアがあり、このように _ _ で真ん中のスペースが削除されます。
dir() 関数
設定された関数 dir() は、モジュール内で定義されたすべての名前を検索できます。文字列のリストとして返されます。
>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__',
'__package__', '__stderr__', '__stdin__', '__stdout__',
'_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe',
'_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv',
'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder',
'call_tracing', 'callstats', 'copyright', 'displayhook',
'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix',
'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount',
'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path',
'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1',
'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit',
'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout',
'thread_info', 'version', 'version_info', 'warnoptions']
引数が指定されていない場合、 dir() 関数は現在定義されているすべての名前をリストします。
C:\Users\Lenovo>cd Desktop
C:\Users\Lenovo\Desktop>python
Python 3.11.4 (tags/v3.11.4:d2340ef, Jun 7 2023, 05:45:37) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
>>> a=[1,2,3,4,5]
>>> import fibo
>>> fib=fibo.fib
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'fib', 'fibo']
>>> a = 5 # 建立一个新的变量 'a'
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'fib', 'fibo']
>>>
>>> del a # 删除变量名a
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'fib', 'fibo']
>>>
標準モジュール
Python 自体には、いくつかの標準モジュール ライブラリが付属しています。これらは、Python ライブラリ リファレンス ドキュメント (つまり、後の「ライブラリ リファレンス ドキュメント」) で紹介されます。
一部のモジュールはパーサーに直接組み込まれており、一部の言語の組み込み関数ではありませんが、システム レベルの呼び出しであっても非常に効率的に使用できます。
これらのコンポーネントは、オペレーティング システムに応じてさまざまな形式で構成されます (たとえば、winreg モジュールは Windows システムに対してのみ提供されます)。
すべての Python パーサーに組み込まれている特別なモジュール sys があることに注意してください。変数 sys.ps1 および sys.ps2 は、プライマリ プロンプトとセカンダリ プロンプトに対応する文字列を定義します。
>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('Tarzan!')
Runoob!
C>
バッグ
パッケージは、「ドット モジュール名」を使用して Python モジュールの名前空間を管理する形式です。
たとえば、モジュールの名前が AB の場合、それはパッケージ A 内のサブモジュール B を表します。
モジュールを使用する場合と同様に、異なるモジュール間のグローバル変数の相互影響を心配する必要がなく、ドットモジュール名形式を使用することで、異なるライブラリ間でのモジュール名の重複を心配する必要がありません。
このようにして、さまざまな作成者が NumPy モジュールまたは Python グラフィック ライブラリを提供できます。
サウンド ファイルとデータを統一した方法で処理する一連のモジュール (または「パッケージ」と呼ぶ) を設計したいとします。
さまざまなオーディオ ファイル形式 (基本的には、.wav、:file:.aiff、:file:.au などの接尾辞名によって区別されます) が存在するため、異なる形式の間で変換するには、ますます多くのモジュール セットが必要になります。フォーマット。
そして、このオーディオ データにはさまざまな操作 (ミキシング、エコーの追加、イコライザー機能の追加、人工的なステレオ効果の作成など) があるため、これらの操作を処理するためのモジュールのセットも無限に必要になります。
考えられるパッケージ構造 (階層ファイル システム内) を次に示します。
sound/ 顶层包
__init__.py 初始化 sound 包
formats/ 文件格式转换子包
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ 声音效果子包
__init__.py
echo.py
surround.py
reverse.py
...
filters/ filters 子包
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
パッケージをインポートするとき、Python は sys.path 内のディレクトリに基づいてパッケージに含まれるサブディレクトリを検索します。
ディレクトリは、_ init _.py というファイルが含まれている場合にのみパッケージとして認識されます。これは主に、決まり文句の名前 (文字列など) が検索パス内の有効なモジュールに誤って影響を与えるのを防ぐためです。
最も単純なケースでは、空の :file:_ init _.py を置くだけです。もちろん、このファイルには初期化コードを含めたり、__all__ 変数 (後で紹介します) に値を割り当てたりすることもできます。
ユーザーは、一度に 1 つのパッケージ内の次のような特定のモジュールのみをインポートできます。
import sound.effects.echo
これにより、サブモジュール sound.Effects.echo がインポートされます。以下にアクセスするにはフルネームを使用する必要があります。
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
サブモジュールをインポートする別の方法は次のとおりです。
from sound.effects import echo
これはサブモジュール echo もインポートしますが、長いプレフィックスは必要ないので、次のように使用できます。
echo.echofilter(input, output, delay=0.7, atten=4)
もう 1 つのバリエーションは、関数または変数を直接インポートすることです。
from sound.effects.echo import echofilter
同様に、このメソッドはサブモジュール echo をインポートし、その echofilter() 関数を直接使用できます。
echofilter(input, output, delay=0.7, atten=4)
from package import itemを使用する場合、対応する項目はパッケージ内のサブモジュール (サブパッケージ)、またはパッケージ内で定義されている関数、クラス、変数などの他の名前である可能性があることに注意してください。
インポート構文は、最初にitem をパッケージ定義の名前として扱いますが、見つからない場合は、モジュールとしてインポートしようとします。見つからない場合は、:exc:ImportError例外がスローされます。
逆に、import item.subitem.subsubitemなどのインポート形式を使用する場合は、最後の項目を除いてすべてパッケージである必要があります。最後の項目はモジュールまたはパッケージにすることができますが、クラス名にすることはできません、関数または変数。
パッケージからインポート*
from sound.Effects import * を使用するとどうなるでしょうか?
Python はファイル システムに移動し、パッケージ内のすべてのサブモジュールを検索し、それらを 1 つずつインポートします。
ただし、 Windows は大文字と小文字を区別しないシステムであるため、この方法はWindowsプラットフォームではあまりうまく機能しません。
Windowsプラットフォームでは、モジュールとしてインポートされたECHO.pyというファイルがechoなのかEchoなのか、それともECHO なのかを判断できません。
この問題を解決するには、正確なパッケージ インデックスを提供するだけで済みます。
import ステートメントは次の規則に従います。 パッケージ定義ファイル_ init _.pyに_ all _というリスト変数がある場合、 **from package import *** を使用すると、このリスト内のすべての名前がパッケージ コンテンツとしてインポートされます。 . .
パッケージの作成者として、パッケージを更新した後に_all_も更新されることを忘れないでください。
次の例には、 file:sounds/Effects/_ init _.pyに次のコードが含まれています。
__all__ = ["echo", "surround", "reverse"]
これは、from sound.Effects import * を使用すると、パッケージ内のこれら 3 つのサブモジュールのみをインポートすることを意味します。
_all_が実際に定義されていない場合、 * from sound.Effects importという構文を使用すると、sound.Effectsパッケージ内のサブモジュールはインポートされません。パッケージ sound.Effects とその中で定義されているすべてのものをインポートするだけです (おそらく_ init _.pyで定義された初期化コードを実行します)。
これにより、_ init _.pyで定義されたすべての名前がインポートされます。また、この文の前にインポートした明示的に指定されたモジュールがすべて破棄されるわけではありません。コードのこの部分を見てください。
import sound.effects.echo
import sound.effects.surround
from sound.effects import *
この例では、from...importを実行する前に、sound.Effectsパッケージ内のエコーモジュールとサラウンドモジュールが現在の名前空間にインポートされます。(もちろん_ all _が定義されていても問題ありません)
* この方法ではコードの可読性が低下することが多いため、通常、この方法を使用してモジュールをインポートすることはお勧めしません。ただし、これにより多くのキーストロークが節約され、一部のモジュールは特定の方法でのみインポートされるように設計されています。
from Package import specific_submoduleを使用すれば間違いはありません。実際、これが推奨されるアプローチです。ただし、インポートするサブモジュールが別のパッケージのサブモジュールと同じ名前を持つ可能性がある場合は除きます。
パッケージが構造内のサブパッケージ (この例のサウンドパッケージなど) で、兄弟パッケージ (同じレベルのパッケージ) をインポートする場合は、インポート絶対パスを使用してインポートする必要があります。たとえば、モジュールsound.filters.vocoder がパッケージsound.Effects内のモジュールechoを使用したい場合は、 from sound.Effects import echoと記述します。
from . import echo
from .. import formats
from ..filters import equalizer
相対インポートは、暗黙的か明示的かに関係なく、現在のモジュールから開始されます。メインモジュールの名前は常に「_ main _」となり、Python アプリケーションのメインモジュールは必ず絶対パスで参照する必要があります。
このパッケージには、追加の属性 __path__ も提供されます。これはディレクトリ リストです。これに含まれる各ディレクトリには、このパッケージを提供する __init__.py があります。他の __init__.py を実行する前にこれを定義する必要があります。この変数は、パッケージに含まれるモジュールとサブパッケージに影響を与えるように変更できます。
この関数は一般的には使用されず、通常はパッケージ内のモジュールを拡張するために使用されます。