【pythonステップアップ】importメカニズム
4428 ワード
本文は主にpythonのimportメカニズムを検討し,名前空間,変数役割ドメイン,import文と関連するモジュール,およびパッケージの管理などに関与する.
ネームスペースと役割ドメイン
≪名前空間|Namespace|emdw≫:名前とオブジェクトのバインド関係です.
役割ドメイン:この名前が表示される場所
名前空間はこの名前が「存在しますか?」であることを説明していると理解できます.役割ドメインは、この名前「見えますか?」を説明します.
名前空間は一般的に2つまたは3つありますが、なぜかというと、2つは1つしか存在しません.つまり、内蔵名前空間とグローバル名前空間、もう1つはローカル名前空間です.これは実行時に関数呼び出しに関連すると、この名前空間が生成され、関数呼び出しが終了すると、この名前空間は消えます.だから2つか3つの名前空間があります.
ネームスペースのロード順序は、ネームスペースを内蔵し、実行モジュールのグローバルネームスペースをロードし、最後に関数呼び出しがある場合はローカルネームスペースが表示されます.
名前検索の順序は、ローカル名空間を検索してからグローバル名空間を検索し、最後に組み込み名空間を検索します.いずれも見つからない場合は、
localsとglobals関数
まず、両方とも辞書を返します.keyは名前、valueは名前に対応する値です.名前の通り、
次のように返されます.
グローバルネームスペースで直接使用します.
返される内容は次のとおりです.
実は全く同じ内容です.
importとload
モジュールはロード時に実行されます.つまり、モジュールの最上位にあるすべてのコードが実行され、インポート(import)は複数回インポートできますが、モジュールは1回しかロードされません.
たとえばpyファイルが3つあります.
py1.py
py2.py
main.py
mainを実行するとpyの場合、印刷結果は:私たちは しかし が印刷される に戻るが
まとめ:モジュールの最上位コード(単純にはインデントされていないコード)は
zip方式のインポート
pythonはzip方式のインポートをサポートし、pythonはzipファイルを通常の使用方法と同じディレクトリ(つまりパッケージ)と見なします.
pycファイル
reload関数
python 3には
相互参照
ネームスペースと役割ドメイン
≪名前空間|Namespace|emdw≫:名前とオブジェクトのバインド関係です.
役割ドメイン:この名前が表示される場所
名前空間はこの名前が「存在しますか?」であることを説明していると理解できます.役割ドメインは、この名前「見えますか?」を説明します.
名前空間は一般的に2つまたは3つありますが、なぜかというと、2つは1つしか存在しません.つまり、内蔵名前空間とグローバル名前空間、もう1つはローカル名前空間です.これは実行時に関数呼び出しに関連すると、この名前空間が生成され、関数呼び出しが終了すると、この名前空間は消えます.だから2つか3つの名前空間があります.
ネームスペースのロード順序は、ネームスペースを内蔵し、実行モジュールのグローバルネームスペースをロードし、最後に関数呼び出しがある場合はローカルネームスペースが表示されます.
名前検索の順序は、ローカル名空間を検索してからグローバル名空間を検索し、最後に組み込み名空間を検索します.いずれも見つからない場合は、
NameError
の異常が放出されます.これで変数のオーバーライドがよく理解できます.なぜ関数の中に外部と同じ名前の変数があるのか、外部の変数ではなくこの関数の内部の変数を使用しています.ローカル名空間を検索するときに見つかったので、検索を続けるのではなく、それを使用します.localsとglobals関数
まず、両方とも辞書を返します.keyは名前、valueは名前に対応する値です.名前の通り、
locals
関数は現在の呼び出し元のローカル名空間を返し、globals
は現在の呼び出し元のグローバル名空間(つまり、どのグローバルの属性にアクセスできるか)を返します.グローバルネームスペースでは、同じ内容が返されます.A = 1
def f(x):
y = 1
print(globals())
print(locals())
f(2)
次のように返されます.
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.sourcefileloader object="" at="">, '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': 'D:/pycharm_wk/ETL/test.py', '__cached__': None, 'A': 1, 'f': }
{'y': 1, 'x': 2}
locals
は{'y': 1, 'x': 2}
を返し、globals
は多くの内容を返していることがわかります.グローバルネームスペースで直接使用します.
print(globals())
print(locals())
返される内容は次のとおりです.
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.sourcefileloader object="" at="">, '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': 'D:/pycharm_wk/ETL/test.py', '__cached__': None}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.sourcefileloader object="" at="">, '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': 'D:/pycharm_wk/ETL/test.py', '__cached__': None}
実は全く同じ内容です.
__name__
および__main__
__name__
は、モジュール名、関数名、クラス名などの名前を示すことを知っていますが、__main__
は、モジュールが直接実行される場合にのみ、__name__
は__main__
に等しくなります.importとload
モジュールはロード時に実行されます.つまり、モジュールの最上位にあるすべてのコードが実行され、インポート(import)は複数回インポートできますが、モジュールは1回しかロードされません.
たとえばpyファイルが3つあります.
py1.py
print('py1')
py2.py
import py1
print('py2')
main.py
import py2
import py1
print('main')
mainを実行するとpyの場合、印刷結果は:
py1
py2
main
main.py
の中でimport py2
をロードして、まずpy2.py
を実行します.py2.py
はまたimport py1
が導入されているのでpy1.py
がロードされ実行されるので、先にpy1
,py1.py
ロード完了後、py2.py
,印刷py2
,実行完了後main.py
,import py1
に遭遇し、pythonはpy1
がすでにimport
されていると判断し、import
を繰り返すことはないので、以下の印刷main
を実行する.まとめ:モジュールの最上位コード(単純にはインデントされていないコード)は
import
のときに実行されますが、複数回import
は1回しか実行されません.zip方式のインポート
pythonはzip方式のインポートをサポートし、pythonはzipファイルを通常の使用方法と同じディレクトリ(つまりパッケージ)と見なします.
pycファイル
python -m py_compile dst.py
を通じてdst.py
ファイルを対応するpyc
ファイルにコンパイルすることができます.import
を使って初めてモジュールをインポートしたとき、pythonは先にloadします.実はインポートを実行したモジュールで、pycファイルを生成しました.インポートもこの内容です.pycファイルを提供する必要はありません.他人の導入も有効だ.reload関数
python 3には
reload
組み込み関数はありません.impモジュールとimportモジュールを使用して同様の機能を実現でき、より多くの有用な関数を提供します.__import__
関数相互参照