UPD: この回答を指摘してくれた Konrad と kqr に感謝します。この回答は C または C++ スタイルのコンパイルについてのみ述べています。たとえば、Common Lisp が行っているように、他の方法もあります。
厳密に言えば、コンパイル時に必ずしも完全なソースコードを持っているとは限らないため、事前に Python プログラムをコンパイルすることはできません。Python プログラムは、ソース コードをダウンロードしてeval()
、私たちが知っているすべてのことを行うことができます。または、プログラムで構築します(標準ライブラリでは、実際にはそれを正確に行いnamedtuple()
ます)。
ただし、これは最大の問題ではありません。これらは限界的な慣行です。最大の問題は、事前にデータ型を推測することが信じられないほど困難であり、一般的にはおそらく不可能だということです。関数があり、それをネイティブ コードにコンパイルする場合は、とmax(x, y)
の可能な型を把握し、組み合わせごとに異なるバージョンをコンパイルする必要があります。それは問題かもしれません。現在、いくつかの機能を制限して、そのような推論を可能にすることができ、RPython を取得できます。x
y
したがって、python プログラムをコンパイルすることはできますが、事前に完全に行うのは困難です。
PyPy があるのはそのためです。PyPy はJIT コンパイラです。推論する代わりに、コードを実行し、実行中に分析します。そのため、実際にはループのみを最適化します。これがどのように機能するかです(非常に大まかに):
- PyPy は、フローに関するデータを収集しながら (現在は 1000 回の反復)、干渉することなくループを実行します。
- 収集したデータ型とフローに基づいて、最適化されたアセンブラ コードが生成され、コンパイルされます。
- 実際のプログラム フローが予測に対応するかどうかをチェックするために、「ガード」が配置されます。
- ネイティブ コードは、ガードが起動するかループが終了するまで実行されます。
また、PyPy の開発中に、開発者は RPython を作成しました。これは、実際には完全かつ静的にコンパイルできる Python のサブセットです。彼らは主に早期バインディングを強制することでそれを達成しました。たとえば、整数である変数がある場合、後でそれを char として転用することはできません。また、リストや他のコンテナなどに異なるデータ型を混在させることはできません。