Pythonがコンパイラを必要としないのはなぜだろうか(コンパイラを必要とするC ++で始めたのだ)
コードを入力して、execとして保存し、実行するだけです。C ++では、ビルドとその他すべての楽しいものを作成する必要があります。
python
て.pyファイルを解釈するか、IDLEまたはEclipseを使用する場合、IDEが自動的に実行します。
Pythonがコンパイラを必要としないのはなぜだろうか(コンパイラを必要とするC ++で始めたのだ)
コードを入力して、execとして保存し、実行するだけです。C ++では、ビルドとその他すべての楽しいものを作成する必要があります。
python
て.pyファイルを解釈するか、IDLEまたはEclipseを使用する場合、IDEが自動的に実行します。
回答:
Pythonにはコンパイラがあります!自動的に実行されるため、気づかないだけです。ただし、そこにあることはわかります。自分のモジュール用に生成されたファイル.pyc
(または.pyo
オプティマイザーを有効にしている場合)を見てくださいimport
。
また、ネイティブマシンのコードにコンパイルしません。代わりに、仮想マシンで使用されるバイトコードにコンパイルします。仮想マシン自体はコンパイルされたプログラムです。これは、Javaの動作に非常に似ています。実際、非常に似ており、代わりにJava仮想マシンのバイトコードにコンパイルされるPythonバリアント(Jython)があります!また、MicrosoftのCLR(.NETで使用)にコンパイルされるIronPythonもあります。(通常のPythonバイトコードコンパイラは、これらの選択肢と区別するためにCPythonと呼ばれることもあります。)
C ++は、言語自体が不完全であるため、コンパイルプロセスを公開する必要があります。プログラムをビルドするためにリンカが必要とするすべてを指定するわけではなく、コンパイルオプションを移植可能に指定することもできません(一部のコンパイラではを使用できますが#pragma
、これは標準ではありません)。したがって、メイクファイルと場合によっては自動地獄(autoconf / automake / libtool)で残りの作業を行う必要があります。これは、実際にCがそれを行った方法からのホールドオーバーです。そして、Cがそのようにしたのは、コンパイラが簡単になったからです。これが人気の理由の1つです(80年代に誰でも簡単なCコンパイラを開発できたのです)。
コンパイラまたはリンカーの動作に影響を与える可能性があるが、CまたはC ++の構文内で指定されていないもの:
これらの一部は検出できますが、指定することはできません。たとえば、どのC ++がで使用されているかを検出__cplusplus
できますが、C ++ 98がコード内でコードに使用されていることを指定できません。Makefileでフラグとしてコンパイラーに渡すか、ダイアログで設定する必要があります。
「依存関係解決」システムがコンパイラに存在し、依存関係レコードを自動的に生成すると考えるかもしれませんが、これらのレコードは特定のソースファイルが使用するヘッダーファイルのみを示します。実行可能プログラムにリンクするために追加のソースコードモジュールが必要かどうかを示すことはできません。CまたはC ++には、特定のヘッダーファイルが単なる束ではなく別のソースコードモジュールのインターフェイス定義であることを示す標準的な方法がないためです繰り返したくないように、複数の場所に表示したい行。ファイルの命名規則には伝統がありますが、これらはコンパイラとリンカによって知られていないか強制されていません。
これらのいくつかはを使用して設定できます#pragma
が、これは非標準であり、標準について話していました。これらはすべて、標準で指定できますが、下位互換性のために作成されたものではありません。一般的な知恵は、メイクファイルとIDEが破損しないため、修正しないでください。
Pythonはこのすべてを言語で処理します。たとえばimport
、明示的なモジュール依存関係を指定し、依存関係ツリーを暗黙指定し、モジュールはヘッダーファイルとソースファイル(つまり、インターフェイスと実装)に分割されません。
Pythonはインタープリター言語です。これは、Pythonコードを読み取り、「命令」をマシンに送信するソフトウェアがコンピューター上にあることを意味します。インタプリタ言語のWikipediaの記事は、興味があるかもしれません。
C ++(コンパイル済み言語)などの言語がコンパイルされると、実行時にハードウェアによって直接読み取られるマシンコードに変換されます。コンパイル言語でWikipediaの記事は面白いコントラストを提供するかもしれません。
コンパイルされたすべての言語に、面内編集-コンパイル-リンク-実行サイクルがあるわけではありません。
実行しているのは、C ++(または少なくともC ++実装)の機能/制限です。
何かを行うには、コードをファイルに保存し、リンクと呼ばれるプロセスでモノリシックイメージを構築する必要があります。
特に、コンパイルと解釈の区別と間違われるのは、このモノリシックリンクプロセスです。
一部の言語は、機械コードへのコンパイルを排除するのではなく、不器用なモノリシックリンク手順を排除することで、これらすべてをはるかに動的に行います。ソースは引き続きオブジェクトファイルにコンパイルされますが、これらはモノリシック実行可能ファイルにリンクされるのではなく、ランタイムイメージにロードされます。
「このモジュールをリロードする」と言うと、何らかのモード切り替えに応じて、ソースをロードして解釈するか、コンパイルします。
Linuxカーネルプログラミングには、Cで作業している場合でもこのような特徴があります。モジュールを再コンパイルして、ロードおよびアンロードできます。もちろん、あなたはまだ実行可能なものを作成していることを認識しており、それは複雑なビルドシステムによって管理されており、まだいくつかの手動ステップがあります。しかし、実際には、最終的にその小さなモジュールだけをアンロードおよび再ロードでき、カーネル全体を再起動する必要はありません。
一部の言語では、これよりもさらにきめ細かいモジュール化が行われており、ビルドとロードはランタイム内から行われるため、よりシームレスです。
最初の質問からの転換...言及されていない点は、Pythonプログラムのソースはあなたが使用して配布するものであり、ユーザーの観点からはそれがプログラムであるということです。よく定義されていないカテゴリに物事を単純化する傾向があります。
コンパイルされたプログラムは通常、マシンコードのスタンドアロンファイルと見なされます。(明らかに、特定のオペレーティングシステムに関連付けられたダイナミックリンクライブラリへのリンクが含まれていることがよくあります)。これは...コンパイルまたは解釈されると説明できるほとんどのプログラミング言語のバリエーションがあります。
Pythonは、簡単にアクセスまたは配布できる形式で作成されるマシンコードを保存せずにコードをコンパイルおよび実行するアプリケーション(インタープリターと呼ばれる)に依存するため、コンパイラーを必要としません。
すべてのプログラミング言語では、人間の概念をターゲットマシンコードに翻訳する必要があります。アセンブリ言語でさえ機械語に翻訳する必要があります。この変換は通常、次の段階で行われます。
フェーズ1:分析と中間コードへの変換(解析)。フェーズ2:外部参照用のプレースホルダーを使用して、中間コードをターゲットマシンコードに変換します。フェーズ3:外部参照の解決およびマシン実行可能プログラムへのパッケージ化。
この翻訳は、多くの場合、プリコンパイルおよび「ジャストインタイム」(JIT)またはランタイムコンパイルと呼ばれます。
C、C ++、COBOL、Fortran、Pascal(すべてではない)、およびAssemblyなどの言語は、インタープリターを必要とせずにオペレーティングシステムによって直接実行できるプリコンパイル言語です。
Java、BASIC、C#、Pythonなどの言語が解釈されます。それらはすべて、フェーズ1で作成された中間コードを使用しますが、マシンコードへの変換方法が異なる場合があります。最も単純な形式では、その中間コードを使用して、期待される動作を行うマシンコードルーチンを実行します。その他は、中間コードをマシンコードにコンパイルし、実行時に外部依存関係の修正を行います。コンパイルするとすぐに実行できます。同様に、マシンコードは以前にコンパイルされた再利用可能なマシンコードのキャッシュに保存され、後で関数が再び必要になった場合に後で再利用できます。関数が既にキャッシュされている場合、インタプリタは再度コンパイルする必要はありません。
最新の高レベル言語は、インタプリタ(JITを使用)カテゴリに分類されます。プリコンパイルされるのは、主にCやC ++などの古い言語です。