.. _getting-start-with-python3: ================ Python3 の基礎 ================ .. contents:: 目次 :depth: 4 .. _documentations-for-python: Python3 に関して参考になる資料等 ================================ 今時のプログラミング言語は、公式ページのドキュメントが大変充実しています。 何らかのプログラミング経験者であれば、公式ページの Python 3 ドキュメントにある チュートリアルやリファレンスマニュアルを参考にすれば入門用としては十分なレベルの情報が得られるでしょう。 機械学習の分野では今や鳥を落とす勢いで人気を博している為、公式以外からも質の高い資料が多数発表されています。 主だったものを用語集の :term:`Python` のところにまとめておきましたので参考にしてください。 Hello world ============= まず最初に、新しいプログラミング言語を学ぶ儀式として、 世界で最も有名なプログラムの一つである `hello world`_ の書き方を確認してみましょう。 Hello world は C 言語のバイブルである通称 K&R こと「 `B.W.カーニハン / D.M.リッチー 著 プログラミング言語 C`_ 」の一番最初に紹介されるプログラムです。 これに因んで多くのプログラミング言語では、チュートリアルの最初で hello world を表示させるプログラムの書き方を紹介しています。 一種の様式美と言ってもよいでしょう。 .. _hello world: https://ja.wikipedia.org/wiki/Hello_world .. _`B.W.カーニハン / D.M.リッチー 著 プログラミング言語 C`: https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9EC C言語の hello world --------------------- オリジナルであるC言語の hello world は :numref:`hello.c` の通りです。 .. literalinclude:: hello.c :language: c :caption: C言語の hello world (:download:`hello.c `) :name: hello.c :class: forCnP C言語はコンパイラ型の言語なので、プログラムを実行する前にソースコードをコンパイラと呼ばれるプログラムにかけることで、 CPU が直接解釈・実行可能な機械語のプログラムに翻訳しておく必要があります。 この作業をコンパイルと呼びます。 POSIX 環境ではC言語のコンパイラ(Cコンパイラ)として cc コマンドが用意されています。 C言語版 hello world のソースコードを保存してあるファイル hello.c を cc コマンドでコンパイルした後、 得られた実行ファイル a.out を実行した例を :numref:`hello.c のコンパイルと実行例` に示します。 [#Warningに関する補足]_ hello.c をダウンロードしたフォルダを POSIX 環境で端末の作業ディレクトリにした状態で試してみましょう。 .. code-block:: console :caption: POSIX 環境におけるC言語版 hello world のコンパイルと実行例 :name: hello.c のコンパイルと実行例 $ # ソースコード(hello.c)をCコンパイラーでコンパイルして実行ファイル(a.out)を得る $ cc hello.c hello.c:3:1: warning: return type defaults to ‘int’ [-Wimplicit-int] 3 | main() | ^~~~ $ # 得られた実行ファイル(a.out)を実行する $ ./a.out hello, world .. [#Warningに関する補足] 念の為補足しておきますが、見ての通り、コンパイル時に警告(warning)が出ています。 これはオリジナルの hello world では main() 関数の定義に必要な戻り値の型を省略していることが原因です。 この例では、コンパイルと実行に支障は出ていませんが、 警告が出る書き方を無視して放置しているとバグの発生原因になる可能性もあります。 原因を確認すると共に、警告が出ない書き方に修正するよう心がけてください。 Python3 の hello world ------------------------- Hello world を Python3 で書くと :numref:`hello.py` のようになります。 .. literalinclude:: hello.py :language: python3 :caption: Python3 の hello world (:download:`hello.py `) :name: hello.py :class: forCnP Python はインタプリタ型の言語なので、ソースコードをインタプリタのコマンドにそのまま渡すことで即実行可能です。 Python3 版 hello world のソースコードが保存されたファイル hello.py を Python3 のインタプリタである python3 コマンドに渡して実行した例を :numref:`hello.py の実行例` に示します。 .. code-block:: console :caption: POSIX 環境における Python3 版 hello world の実行例 :name: hello.py の実行例 $ # ソースコード(hello.py)を Python3 インタプリタに渡して実行する $ python3 hello.py hello, world ところで、 :numref:`hello.py` の 1 行目にある "#!/usr/bin/env python3" という記述に気付いた人はいるでしょうか? Python では "#" から行末までをコメントとして扱うためこの行はプログラムとして解釈されません。 一方 POSIX 環境の shell は実行属性の付与されたファイルの先頭が "#!" で始まっていると、 1 行目の 3 文字目以降に書かれている内容を、インタプリタのコマンドの指定として解釈する仕組みがあります。 この仕組み及び 1 行目の記述方法は `shebang (シバン)`_ と呼ばれています。 .. _shebang (シバン): https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%90%E3%83%B3_(Unix) Python を始めとした UNIX 系のスクリプト言語の多くは、 "#" から行末までをコメントとして扱う点に共通性が認められます。 これはおそらく shebang の仕組みに根ざすところが大きいでしょう。 スクリプト言語のソースファイルに shebang と実行属性が設定されている場合、 ソースファイルを与えてインタプリタコマンドを実行せずとも、 ソースファイルを直接実行することが可能になります( :numref:`hello.py を直接実行した例` )。 .. code-block:: console :caption: hello.py を直接実行した例 :name: hello.py を直接実行した例 $ ./hello.py hello, world もし hello.py に実行属性が付与されてない場合、 :numref:`hello.py を直接実行した例 (許可がありません)` または :numref:`hello.py を直接実行した例 (Permission denied)` のような エラーになるでしょう。 .. code-block:: console :caption: hello.py を直接実行した例 (実行属性がない場合: 和文エラー表示) :name: hello.py を直接実行した例 (許可がありません) $ ./hello.py bash: ./hello.py: 許可がありません .. code-block:: console :caption: hello.py を直接実行した例 (実行属性がない場合: 英文エラー表示) :name: hello.py を直接実行した例 (Permission denied) $ ./hello.py bash: ./hello.py: Permission denied この場合、ls コマンドの -l オプションでファイルの属性に実行属性(x)が付与されているか確認すると共に、 chmod コマンドの +x オプションを用いてソースファイルに実行属性を与えます( :numref:`hello.py - check execute flag` )。 .. code-block:: console :caption: 実行属性の確認と付与 :name: hello.py - check execute flag $ # ファイル属性の確認 $ ls -l hello.py -rw-rw-r-- 1 user group 45 5月 22 21:38 hello.py $ # ファイルに実行属性を付与 $ chmod +x hello.py $ # 再度ファイル属性の確認 $ ls -l hello.py -rwxrwxr-x 1 user group 45 5月 22 21:38 hello.py Python3 の REPL 環境で hello world ----------------------------------- C言語にはない Python の特徴の一つとして、 `REPL (Read-Eval-Print Loop)`_ と呼ばれる対話型の実行環境があります。 .. _REPL (Read-Eval-Print Loop): https://google.com/search?q=REPL+Read-Eval-Print+Loop コマンドライン引数を与えず、単独で ``python3`` コマンド(:numref:`Python3_REPL`)を実行すると REPL 環境が起動します(:numref:`Python3_REPL_start`)。 .. code-block:: bash :class: forCnP :caption: Python3 の REPL 環境用のコマンド :name: Python3_REPL python3 .. code-block:: console :caption: Python3 の REPL 環境が起動した状態 :name: Python3_REPL_start $ python3 Python 3.8.10 (default, Nov 26 2021, 20:14:08) [GCC 9.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> ここにキーボードから ``print("hello, world")`` (:numref:`Python3_REPL_hello`)と対話的に入力して [ENTER] キーを叩くと、 対話的に結果が得られます(:numref:`result of Python3_REPL_hello`)。 .. code-block:: python3 :caption: Python3 の REPL 環境に入力する hello world :name: Python3_REPL_hello :class: forCnP print("hello, world") .. code-block:: console :caption: Python3 の REPL 環境で対話的に実行した hello world の結果 :name: result of Python3_REPL_hello $ python3 Python 3.8.10 (default, Nov 26 2021, 20:14:08) [GCC 9.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> print("hello, world") hello, world >>> REPL では shell と同じように history と呼ばれる機能が利用できます。 カーソルキーの上下で以前入力して実行した内容を呼び出すとともに編集、再実行が可能です。 何度も同じような命令を打つ必要はありません。 Jupyter notebook で hello world ---------------------------------- :ref:`starting_jupyter_notebook` で少し紹介していますが、 Jupyter notebook も対話型のプログラミング環境なので、 REPL でやる場合とほぼ同じです。 ただし、Jupyter notebook では、 ブラウザ上で前後のコードブロックを行ったり来たりしながら、 その内容の編集や再実行が可能となっています。 試しに、コードブロックに ``print("hello, world")`` と入力して実行してみましょう (:numref:`fig_helloworld_ipynb.png`)。 .. figure:: fig_helloworld_ipynb.png :name: fig_helloworld_ipynb.png Jupyter notebook で hello world. 標準入出力とパイプ、リダイレクト ================================= Python の input() や print() による入出力は 標準入出力と呼ばれる仕組みを利用しています。 標準入出力は :doc:`POSIX` で紹介した :ref:`pipeline` や :ref:`redirect` で扱う事が出来るので、 Python 側のプログラムとしてファイル入出力を実装しなくても input() や print() からファイルに対する簡易的な入出力を行うことが可能です。 例えば、 :numref:`hello.py` の結果をファイルに保存するには :numref:`hello.py > hello.txt` のようにします(:numref:`result of hello.py > hello.txt`)。 .. code-block:: bash :class: forCnP :name: hello.py > hello.txt :caption: hello.py の出力をファイルへ保存する例 ./hello.py > hello.txt .. code-block:: bash :class: forCnP :name: result of hello.py > hello.txt :caption: hello.py の出力をファイルへ保存する例実行結果 $ ./hello.py > hello.txt $ cat hello.txt hello, world また、input() を持ちいてキーボードから入力したデータを処理する :numref:`stdio_001.py` 、 :numref:`stdio_002.py` のような プログラムがあったとします。 .. literalinclude:: stdio_001.py :language: python3 :caption: 文字列の足し算 (:download:`stdio_001.py `) :name: stdio_001.py :class: forCnP .. literalinclude:: stdio_002.py :language: python3 :caption: 数値の足し算 (:download:`stdio_002.py `) :name: stdio_002.py :class: forCnP これは、そのまま Jupyter notebook に貼り付ければ :numref:`stdio_001,002.ipynb.png` のように実行可能です。 .. figure:: stdio_001,002.ipynb.png :name: stdio_001,002.ipynb.png stdio_001.py と stdio_002.py の Jupyter notebook による実行結果 しかし、input() による入力は手で入力しなければなりません。 コマンドラインから実行する際も同様ですが、 パイプやリダイレクトを用いると input() や print() 等、標準入出力を前提としたプログラムの 入力を自動化したり出力をファイルに記録することが容易にできます ( :numref:`stdio_001.py with pipe`、 :numref:`stdio_002.py with pipe`、 :numref:`result of stdio_001.py with pipe`、 :numref:`result of stdio_002.py with pipe`、 )。 .. code-block:: bash :class: forCnP :name: stdio_001.py with pipe :caption: stdio_001.py へパイプラインを渡す例 echo -e "1\n2" | ./stdio_001.py .. code-block:: bash :class: forCnP :name: stdio_002.py with pipe :caption: stdio_002.py へパイプラインを渡す例 echo -e "1\n2" | ./stdio_002.py .. code-block:: console :name: result of stdio_001.py with pipe :caption: stdio_001.py へパイプラインを渡す例実行結果 $ echo -e "1\n2" | ./stdio_001.py a = b = a + b = 12 .. code-block:: console :name: result of stdio_002.py with pipe :caption: stdio_002.py へパイプラインを渡す例実行結果 $ echo -e "1\n2" | ./stdio_002.py a = b = a + b = 3 または、:numref:`stdio_001_in.txt` のようなデータファイルがあれば、 :numref:`stdio_001.py with redirect` のようにファイルから標準入力へリダイレクト することも出来ます。 .. literalinclude:: stdio_001_in.txt :language: python3 :caption: 足し算用のデータファイル (:download:`stdio_001_in.txt`) :name: stdio_001_in.txt :class: forCnP .. code-block:: bash :class: forCnP :name: stdio_001.py with redirect :caption: stdio_001.py へリダイレクトを渡す例 ./stdio_001.py < stdio_001_in.txt .. code-block:: :name: result of stdio_001.py with redirect :caption: stdio_001.py へリダイレクトを渡す例実行結果 $ ./stdio_001.py < stdio_001_in.txt a = b = a + b = 12 input() の出力である "a = " や "b = " がちょっと邪魔ですが、 パラメータを外部ファイルとして用意して、結果をファイルに保存する等の ちょっとした用途に使えるでしょう。