【pythonステップアップ】importメカニズム

4428 ワード

本文は主にpythonのimportメカニズムを検討し,名前空間,変数役割ドメイン,import文と関連するモジュール,およびパッケージの管理などに関与する.
ネームスペースと役割ドメイン
≪名前空間|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__関数
    相互参照