モジュールはPythonで唯一の真のグローバルオブジェクトであり、他のすべてのグローバルデータはモジュールシステム(sys.modulesをレジストリとして使用)に基づいています。パッケージは、サブモジュールをインポートするための特別なセマンティクスを持つ単なるモジュールです。.pyファイルを.pycまたは.pyoに「コンパイル」することは、ほとんどの言語で理解されているようにコンパイルされません。構文をチェックし、インタープリターで実行されるとモジュールオブジェクトを作成するコードオブジェクトを作成するだけです。
example.py:
print "Creating %s module." % __name__
def show_def(f):
print "Creating function %s.%s." % (__name__, f.__name__)
return f
@show_def
def a():
print "called: %s.a" % __name__
インタラクティブセッション:
>>> import example
# first sys.modules['example'] is checked
# since it doesn't exist, example.py is found and "compiled" to example.pyc
# (since example.pyc doesn't exist, same would happen if it was outdated, etc.)
Creating example module. # module code is executed
Creating function example.a. # def statement executed
>>> example.a()
called: example.a
>>> import example
# sys.modules['example'] found, local variable example assigned to that object
# no 'Creating ..' output
>>> d = {"__name__": "fake"}
>>> exec open("example.py") in d
# the first import in this session is very similar to this
# in that it creates a module object (which has a __dict__), initializes a few
# variables in it (__builtins__, __name__, and others---packages' __init__
# modules have their own as well---look at some_module.__dict__.keys() or
# dir(some_module))
# and executes the code from example.py in this dict (or the code object stored
# in example.pyc, etc.)
Creating fake module. # module code is executed
Creating function fake.a. # def statement executed
>>> d.keys()
['__builtins__', '__name__', 'a', 'show_def']
>>> d['a']()
called: fake.a
あなたの質問:
- これらはある意味でコンパイルされますが、Cコンパイラの動作に精通している場合は期待どおりではありません。
is
データが不変である場合、コピーは実行可能であり、オブジェクトID(演算子およびid()
Pythonの場合)を除いて共有と区別がつかないはずです。
- インポートはコードを実行する場合と実行しない場合があり(常にローカル変数をオブジェクトに割り当てますが、問題は発生しません)、sys.modulesを変更する場合と変更しない場合があります。スレッドにインポートしないように注意する必要があります。通常、すべてのインポートをすべてのモジュールの上部で実行するのが最善です。これにより、カスケードグラフが作成されるため、すべてのインポートが一度に実行され、__ main__が続行され、RealWork™が実行されます。 。
- 現在のPEPはわかりませんが、すでに多くの複雑な機械が設置されています。たとえば、パッケージは__path__属性(実際にはパスのリスト)を持つことができるため、サブモジュールは同じディレクトリにある必要はなく、これらのパスは実行時に計算することもできます。(以下のmungepathパッケージの例。)独自のインポートフックを作成し、関数内でimportステートメントを使用し、__ import__を直接呼び出すことができます。パッケージとモジュールを操作する他の2〜3のユニークな方法を見つけても驚かないでしょう。
- インポートシステムのサブセットは、Cの#includeのようなものに類似している限り、従来のコンパイル言語で機能します。コンパイラで「第1レベル」の実行(モジュールオブジェクトの作成)を実行し、それらの結果をコンパイルできます。ただし、これには重大な欠点があり、モジュールレベルのコードと実行時に実行される関数の実行コンテキストを分離することになります(一部の関数は両方のコンテキストで実行する必要があります)。(Pythonでは、defステートメントやclassステートメントも含め、すべてのステートメントが実行時に実行されることに注意してください。)
- これが、従来のコンパイル言語が「トップレベル」コードをクラス、関数、およびオブジェクトの宣言に制限し、この2番目のコンテキストを排除する主な理由であると思います。それでも、注意深く管理しない限り、C / C ++(およびその他)のグローバルオブジェクトの初期化の問題が発生します。
mungepath / __ init __。py:
print __path__
__path__.append(".") # CWD, would be different in non-example code
print __path__
from . import example # this is example.py from above, and is NOT in mungepath/
# note that this is a degenerate case, in that we now have two names for the
# 'same' module: example and mungepath.example, but they're really different
# modules with different functions (use 'is' or 'id()' to verify)
インタラクティブセッション:
>>> import example
Creating example module.
Creating function example.a.
>>> example.__dict__.keys()
['a', '__builtins__', '__file__', 'show_def', '__package__',
'__name__', '__doc__']
>>> import mungepath
['mungepath']
['mungepath', '.']
Creating mungepath.example module.
Creating function mungepath.example.a.
>>> mungepath.example.a()
called: mungepath.example.a
>>> example is mungepath.example
False
>>> example.a is mungepath.example.a
False