サイトアイコン 天文学者のpython・音楽・お料理レシピ

python入門講座 | pythonを使ってみよう3-5(pythonスクリプトを書いてみよう)[第10回]

ポイントを押さえることで、複雑なプログラムも速く正確に書くことができます!

Ciao!みなさんこんにちは!このブログでは主に
(1)pythonデータ解析,
(2)DTM音楽作成,
(3)お料理,
(4)博士転職
の4つのトピックについて発信しています。

今回は「アラサーOLのためのpython入門講座」です!
この講座では、プログラミング初心者アラサーOLのMi坊さんに、pythonを学習する上でのアドバイスを行います!
パソコンもプログラミングも初心者だけど、プログラミングができるようになりたい!」という方のためにstep-by-stepで解説していきます。

今日もpythonのスクリプト(ソースコード)を書く方法をご紹介します!
複雑な処理を行いたい場合、同じ処理を繰り返したい場合などに使う方法です。
前回記事で紹介したPythonスクリプトの書き方のルールと様式に従ってコードを書いていきます。
今回は関数を定義して使ってみるなどの複雑な処理をやってみましょう!

Kaiko

この記事はこんな人におすすめ

  • 初心者だけどpythonを始めた!
  • とりあえずpythonを使ってみたい!
  • 本格的なpythonの動かし方を知りたい!

Abstract | Pythonスクリプトでできることに触れよう!

今回は少し本格的なPythonスクリプトを実際に書いてみて、Pythonスクリプトでできることに触れてみましょう!
Pythonの実行方法はいくつかありますが、スクリプトを書くことのメリットは関数などを使って複雑な処理を組み上げることができたり、同じ処理を繰り返すような場合に実行が簡単(再現性が高い)ということです。
データ分析に限らず、何かしらの処理を行うためのアプリを作ったりする際にはスクリプトを書くことになります。

Pythonスクリプトを書く際には一定のルールと様式を守ると、読みやすいコードを書くことができ、ミスやエラーを減らしたりコーディングに書ける時間を短縮することができます。
今回はこれらのルールや様式に沿って実際にコーディングしてみましょう。
Pythonプログラミング初心者がいきなりスクリプトを書ける必要はありませんが、Pythonを習得するというゴールのイメージを持つために真似してやってみてください!



Background | 前回までのおさらい

実際にPythonのスクリプトを書いていく前に、前回までのおさらいをしましょう。

Pythonでスクリプトを書くメリット

Pythonでスクリプトを書くメリットは、

など、複雑なプログラミングを実現できることや再現性の担保や自動化ができるといった点です。
関数をうまく使ってスクリプトを複雑な処理を速く正確にコーディングすることができます。
また、スクリプトを一度作れば、コマンド一つですべての処理を実行できます。
詳しくは以前の記事「アラサーOL | pythonを使ってみよう3-1(Atomエディタのインストール方法)」をご覧ください。

Pythonでプログラミングして実行する方法には大きく分けて、ターミナル上のコマンドラインで実行する(「アラサーOL|pythonを使ってみよう1|(ターミナルから直接操作する方法)」)、Jupyter Notebookを使う(「アラサーOL|pythonを使ってみよう2 (Jupyter Notebookを使う方法)」)、スクリプトを書く方法の3つがあります。
実現したい処理の複雑さに応じて使い分けると良いでしょう。
サクッと計算するだけならターミナル上で、単発の分析など軽い処理ならJypyter Notebook、複雑な処理を組み上げるならスクリプトといった具合です。



Pythonスクリプトのルールとフォーマット

Pythonスクリプトで複雑な処理を組むことができますが、スクリプトの書き方には一定ルールとフォーマットがあります。
Pythonスクリプトの書き方ルールとして代表的なものが「PEP 8 — Style Guide for Python Code」です。
スペースの数や変数や関数の名前の付け方など、細く書いてあります。
代表的なものは前回記事「アラサーOL | pythonを使ってみよう3-4(pythonスクリプトのルールとフォーマットの基礎知識)」にまとめてありますので、参照してください!
代表的なルールだけでも守るとスッキリとしたコードを書くことができ、作業の高速化、正確性の工場に繋がります!

Pythonスクリプトには「このような内容をこのような順番で記載する」というフォーマットというか段取りがあります。
これが正解ということはないのですが、よくある書き方に合わせて書くと、自分としても書きやすいし、他人に見せたときにも速く理解してもらいます。
やはり作業の高速化、正確性の工場に繋がります!
詳しくは前回記事「アラサーOL | pythonを使ってみよう3-4(pythonスクリプトのルールとフォーマットの基礎知識)」をご覧頂きたいのですが、

  1. メタ情報部分
  2. import部分
  3. parameter定義部分
  4. function(関数)定義部分
  5. main関数部分

という構成で書かれます。
今回はこの段取りで書いていきます!



Introduction | 準備

まずはPythonスクリプトを書く準備をしていきましょう。
Pythonの練習用ファイルを格納しているディレクトリに移動し、新規Pythonスクリプトファイルを作際します。

下準備1 | ディレクトリの移動

まずはPython練習用ディレクトリに移動します。
以前「アラサーOL | pythonを使ってみよう3-3(簡単なpythonスクリプトの書き方と実行方法)」と同様、ホーム直下のpython練習用ディレクトリ「python_practice」を使います。
今回もここにスクリプトファイルを作成します。

操作はターミナルで行いましょう。
ターミナルを立ち上げたら

cd ~/python_practice

でpython練習用ディレクトリに移動します。
ターミナルの立ち上げ方は過去の記事「アラサーOL|ターミナル操作入門(pythonを学び始める前に1)」をご覧ください。

下準備2 | ファイルの新規作成

まずは新規ファイルを作成しましょう。
ターミナルで

atom hello_arithmetic.py

を実行して「hello_arithmetic.py」というファイルを新規作成し、Atomエディタで開きます。
このファイルを編集して「Hello, world」を出力し、四則演算+αをするスクリプトを作ります。



Method | 基本構成を守ったスクリプトを書いてみよう

実際に基本構成(前回記事「アラサーOL | pythonを使ってみよう3-4(pythonスクリプトのルールとフォーマットの基礎知識)」参照)に沿ったスクリプトを書いてみましょう!
練習のための例として

という機能を持ったスクリプトを書いてみましょう。

メタ情報の記載

では、ここからスクリプトを書いていきます!
Atomエディタでhello_arithmetic.pyを編集します。
最初にメタ情報を書きましょう。

Python定型文の記載 | #!/usr/bin/env python

ファイルの先頭には定型文を記載します。
1行目に

#!/usr/bin/env python

と書きましょう。
ファイル1行目の「#!」で始まる文は特別な意味を持ちます。
この1文はOSにどのプログラムで処理するのかを教えるために使われます。
「#」から始まりますが、この1行だけはコメントではありません。
この場合はpythonなので上記のように書きます。
この1行が持つ意味はとりあえず理解しなくても構いません。「こういう1文を書く決まりがあるのね」ぐらいに思っていただければOKです!
どうしても気になる方は以下の蛇足をお読みください笑

蛇足 | /usr/bin/envの意味

ちなみに「/usr/bin/env」には、どのバージョンのプログラムを使うかなどが規定されています。
試しにターミナルで

/usr/bin/env python

を実行してみましょう。
すると、現在condaでactivateされているpython(python3.9)がちゃんと開きます。
conda(miniforge3)を使ったpythonのバージョン管理は過去記事「アラサーOL|python環境構築入門(python3.9をM1 Macにインストールしよう!)」を参照してください。

さらに試しに、以下のようにしてcondaでpythonのversionを切り替えてみてください。

conda activate py38

これでコマンドプロンプトの先頭が(base)から(py38)に切り替わったら

/usr/bin/env python

を実行してみましょう。今度はpython 3.8が開いたと思います。
実験が終わったら

conda deactivate

でpythonの仮想環境をbaseに戻しておきましょう。

テキストエンコーディングの記載 | # -*- coding: utf-8 -*-

次にエンコーディングを記載します。
スクリプトの3行目に

# -*- coding: utf-8 -*-

と書きましょう。
2行目は空白行にしておきます。
UTF-8でコーディングする際はutf-8と書きます。
実際にはコーディングするときのテキストエンコーディングに合わせて記載しましょう。

テキストエンコーディングとは、文字の情報を機械が扱える符号に変換する規則のことです。
ファイルを読み込むときのテキストエンコーディングが対象ファイルのテキストエンコーディングと合致していない場合には文字化けが起こります。
UTF-8はグローバルに最もよく使われているテキストエンコーディングなので、プログラミングを行う際にはUTF-8にしておくのが良いでしょう。

Atomではウィンドウ下部のバーに現在のテキストエンコーディングが表示されています(図1)。
おそらくUTF-8になっているはずです。
UTF-8になっていなかったら、テキストエンコーディングのところをクリックしてUTF-8に変えておきましょう。

図1. Atomでのテキストエンコーディングの表示

その他メタ情報の記載 | ファイル作成者、編集履歴、概要、使い方など

ファイル作成者、編集履歴、概要、使い方などのその他のメタ情報も記載しておきましょう。
例えば、以下のように記載しておきましょう。
行頭に「#」をつけてコメントで書くか、「”””」で囲ってdocstringで書きましょう
コメントやdocstringの書き方は前回記事「アラサーOL | pythonを使ってみよう3-4(pythonスクリプトのルールとフォーマットの基礎知識)」を参照してください。

# ------------------------- #
# Created By Kaiko on 20210523
# Edit History
#    20210523: File created by Kaiko with MacOS 11.2.3, Python 3.9.2
# ------------------------- #

"""
Purpose of the script
    1. To learn how to run Python using a script
    2. To print "Hello, world"
    3. To test arithmetic calculation

How to use the script
    python hello_arithmetic.py
"""

最初のブロックにはファイル作成者と編集履歴を書きました。
今後編集するたびに、編集履歴のところに行を追加して履歴を残します。
ここまで詳しく書かなくても良いかもしれませんが、後で見返して誰がいつどのような変更を加えたのかを残しておきましょう。
本格的にプログラミングを行う場合にはファイルのバージョンの履歴も一緒に書いたほうがいいですね。

後段のブロックには概要と使い方を書きました。
こちらもなんのためのファイルなのかがわかるように書けばOKです。
ここまで書いたスクリプトの例を図2に示します。

図2. メタ情報が記載されたスクリプトの例

ちなみにPythonスクリプトのコメントは日本語で書くことも可能です。
PEP-8(PEP 8 — Style Guide for Python Code)では、コメントは原則英語で書くことが推奨されています。
日本語話者以外は絶対に見ないという場合に限って日本語で書いても良いそうです。
私は普段からコメントも英語で書いているので、今回も英語で書いています。



import部分の作成 | ライブラリのimport

つぎにライブラリのimport部分を作りましょう。
ひとまず以下のように記載し、「os, sys, datetime」の3つのライブラリをimportしましょう。

# ------------------------- #
# Import libraries
import os
import sys
import datetime
# ------------------------- #

それぞれのライブラリについてはここではあまり知らなくても良いですが、概ね以下のようなものです。
osとsysはパソコンのOSやシステムとやり取りするためのライブラリです。
osはファイルの存在を確認したり、ディレクトリを作成するときに使います。
sysはスクリプトのメタ情報を取得するときなどに使います。
datetimeは日付や時刻を取得するためのライブラリです。

import文の順番

前回記事では紹介しませんでしたが、ライブラリをimportする順番もPEP-8(PEP 8 — Style Guide for Python Code)で言及されています。

  1. 標準ライブラリ
  2. 外部ライブラリ
  3. ローカルライブラリ

の順番にimportします。
今回のos, sys, datetimeは標準ライブラリなので最初にimportします。
numpy, scipy, pandas, matplotlibは外部ライブラリなので、標準ライブラリのimport文を書ききったあとでimportします。
ローカルライブラリとは自作の関数などをまとめてローカル環境(手元のPC)だけで使えるようにしたものです。
機会があればそのうちご紹介します。

ここまで書いた例を図3に示します。

図3. import部分まで作成したスクリプトの例



parameter定義部分の作成 | グローバルパラメータの定義

次に、「グローバルパラメータ」あるいは「グローバル変数」と呼ばれる変数を定義します。
グローバル変数とは、そのスクリプトのどこからでも参照できる変数のことです。
これの対義語はローカルパラメータあるいはローカル変数で、ある関数内のみ定義され、

プログラミングでは、数値や文字列をベタ打ちせず、変数として定義しておくことが重要です。
何度も使うような数字や文字列は、グローバル変数としてスクリプトの冒頭で1回定義しておきましょう。
そうすれば、変更が必要になったときに1箇所変更すれば済みます。
数値や文字列をベタ打ちせずに変数として定義しておくというのはプログラミングに限らずエクセルなどでも有効な方法です。

今回のスクリプトでは以下のように、3つの文字列・数値を一つの「辞書型変数」として定義します。

#-------------------------#
#- Define global variables - #
p_input = {
    'FILE': "HelloScript.py", # name of file whose existence to be checked
    'STR': "world", # string to be printed after "Hello, "
    'VAR1': 5, # Variable 1 in arithmetic calculation
    'VAR2': 3 # Variable 2 in arithmetic calculation
}

辞書型などの「変数の型」については別の回で解説するので、ここではそういうものがあるぐらいに認識していただければ結構です。
ここで定義した値は「p_input[‘STR’]」などと書けば参照することができます。

ここまで書いた例を図4に示します。

図4. グローバル変数「p_input」の定義まで書いた例



function(関数)部分の作成

次に、プログラムの心臓部である関数を定義します。
今回は

  1. 現在時刻を表示してとファイルの存在を確認する関数
  2. Hello, hogehogeを出力する関数
  3. 四則演算を行って結果を出力する関数

の3つを作ることにします。

関数1 | 現在時刻表示&ファイルの存在確認関数

1つ目の関数を以下のように作ってみましょう。
どの行で何をしているかはまだわからなくて大丈夫です。
ここでは真似するだけで結構です。

#-------------------------#
# - Define functions - #

# - function to print time and file existence - #
def print_time_and_file_existence(file_target):
    """
    arguments:
      file_target: file whose existence is checked
    return:
      0
    """

    # - print current frame - #
    print(' - %s -' % (sys._getframe().f_code.co_name)) # use library 'sys'

    # - print time - #
    time_now = datetime.datetime.now() # get time with datetime library
    print(' Time:', time_now) # time_now contains datetime object

    # - check file existence - #
    result_FileExists = os.path.exists(file_target) # use library 'os'
    if(result_FileExists): # result_FileExists is bool, i.e., True or False
        print(
            ' File "%s" exists. Result = %s' % (
                file_target, result_FileExists))
    else:
        print(
            ' Cannot find file "%s". Result = %s' % (
                file_target, result_FileExists))

    # - end - #
    return 0
#--#
関数の書き方の簡単な説明1 | 関数の定義方法

関数の書き方は別の機会に説明しますが、ここでも簡単に紹介します。
関数は「def hogehoge():」という書き方で始めます。

関数の書き方の簡単な説明2| 引数(arguments) — 関数への入力

カッコの中に「def hogehoge(arg1, arg2,…)」といった形で変数を入れることができます。
これらarg1, arg2などの変数は「引数(arguments)」と呼ばれる変数で、その関数への入力となる値が格納されています。
引数を使うことで、その関数を呼び出すときに好きな値を渡すことができます。
この例の”print_time_and_file_existence”という関数には、存在を確かめたいファイル名を”file_target”という引数で渡します。

関数の書き方の簡単な説明2| 返り値(return) — 関数からの出力

関数で行った処理結果は「return out1, out2,…」という形で関数の外に取り出す(「値を返す」と言います)ことができます。
この例の”print_time_and_file_existence”という関数からは返すものはないので0を返しておきます。

ここまで書いた例を図5に示します。

図.5 関数1まで書いた例

関数2 | Hello, hogehogeを出力する関数

次にHello, hogehogeを出力する関数を作ってみましょう。
hogehogeの部分は引数として渡します。
以下のような関数を作ってみましょう。

# - function to print hello hogehoge - #
def print_hello_hogehoge(hogehoge):
    """
    arguments:
      hogehoge <str>: string to be printed after hello,
    return:
      0
    """

    # - print current frame - #
    print(' - %s -' % (sys._getframe().f_code.co_name)) # use library 'sys'

    # - print hello hogege - #
    print(' Hello,', hogehoge) # same as "print(' Hello, %s' % (hogehoge))"

    # - end - #
    return 0
#--#

先程の関数1よりもだいぶシンプルですね。
「# – print current frame – #」の次の行では、現在実行中の関数名を出力します。
「# – print hello hogehoge – #」の次の行では、”Hello, “に続いて、変数hogehogeの中身を出力します。
もし、hogehogeとして”world”を渡せば”Hello, world”が出力されます。
他の言葉を渡せばその言葉が”Hello”の後に出力されます。

ここまで書いた例を図6に示します。
ちなみに関数と関数の間には2行の空白行を挿入します(PEP 8 — Style Guide for Python Code)。

図6. 関数2まで書いた例

関数3 | 四則演算を行う関数

最後に四則演算を行う関数を作ってみましょう。
以下のように、var1とvar2を引数として渡し、結果をリストという形式で返す「calc_arithmetic」関数を作りましょう。

# - function to carry out arithmetic calculation - #
def calc_arithmetic(var1, var2, verb = True):
    """
    arguments:
      var1 <float>: variable 1 for calculation
      var2 <float>: variable 2 for calculation
      verb <bool>: if True, results are printed
    return:
      cal_results <list of float>: list containing the following values:
        [
            var1 + var2,
            var1 - var2,
            var1 * var2,
            var1 / var2,
            var1 // var2,
            var1 % var2,
            var1 ** var2
        ]
    """

    # - print current frame - #
    print(' - %s -' % (sys._getframe().f_code.co_name)) # use library 'sys'

    # - arithmetic calculation - #
    cal_results = [
        var1 + var2,
        var1 - var2,
        var1 * var2,
        var1 / var2,
        var1 // var2,
        var1 % var2,
        var1 ** var2
    ]

    # - print results if required - #
    if(verb):
        print(' var1 = ', var1)
        print(' var2 = ', var2)
        print(' var1 + var2 = ', cal_results[0])
        print(' var1 - var2 = ', cal_results[1])
        print(' var1 * var2 = ', cal_results[2])
        print(' var1 / var2 = ', cal_results[3])
        print(' var1 // var2 = ', cal_results[4])
        print(' var1 % var2 = ', cal_results[5])
        print(' var1 ** var2 = ', cal_results[6])

    # - end - #
    return cal_results
#--#
2種類の引数 | positional argumentsとoptional arguments

引数にはpositional argumentsとoptional argumentの2種類があります。
この関数”calc_arithmetic”は2つのpositional argumentsと1つのoptional argumentを取ります。

必ず渡す引数: positional arguments

positional argumentsとは、関数を呼び出す際に必ず渡さなければならない引数です。
今回の例で、positional argumentsである引数var1とvar2はfloat(浮動小数点)型という形式です。floatというのは例えば、1.2とか3.56などの数値です。1.0とが3.0など整数値でも構いません。
関数を呼び出すときに

calc_arithmetic(3, 5)

などとして、var1(=3)とvar2(=5)を与えます。

オプションの引数: optional arguments

optional argumentsとは、デフォルト値が定義されているため渡さなくても良い引数です。今回の例では、optional argumentである引数verb(verbatimの略)はbool型です。
bool型というのは”True”と”False”の2値を取る変数です。デフォルト値は”verb = True”というように”True”に設定されています。
bool型変数は今回の例のように

if(varb):
   print(' var1 + var2 = ', cal_results[0])

などとif文に入れるのに便利です。
今回の例ではverbがTrueの場合には計算結果を出力し、Falseの場合には計算だけ行って返り値として返すということにしています。

図7に関数3を書いた例を示します。

図7. 関数3まで書いた例



main関数部分の作成

スクリプトの最後にmain関数部分を作成します。
main関数では、先ほど作成した3つの関数

を呼び出して実行していきます。
以下のように書きます。

#-------------------------#
# main func
if __name__ == '__main__':
    # - use function 1 - #
    print_time_and_file_existence(p_input['FILE'])

    # - use function 2 - #
    print_hello_hogehoge(p_input['STR'])
    
    # - use function 3 - #
    calc_arithmetic(p_input['VAR1'], p_input['VAR2'])

ここまで書いた例を図8に書きます。

図8. main関数まで書いた例

ここまでできたらスクリプトを保存しておきましょう。
「Command + S」のショートカットで保存できます。
スクリプトを書きながらこまめの保存しておくと良いでしょう。

作成例

ここまでできたら「hello_arithmetic.py」は完成です。
参考にhello_arithmetic.pyの作成例をこちら(Github Gist)に置いておきます。
もしわからないところやうまくいかなければ参照してください。



Results | スクリプトの実行

作成したスクリプトを実行してみましょう。
ターミナルのウィンドウに戻ります。
“python_practice”のディレクトリに移動して”hello_arithmetic.py”を実行します。
さきほどAtomで”hello_arithmetic.py”を開いたターミナルウィンドウでOKです。
そのウィンドウで

python hello_arithmetic.py 

を実行しましょう。

実行すると、図9のように表示されるはずです。
ファイル(HelloScript.py)の存在の確認結果(=存在する)や、”Hello, world”の表示、四則演算が行われていますね。

図9. hello_arithmetic.pyの実行結果



Discussion | main関数部分で返り値を取り出したい場合

今回、main関数から呼び出した3つの関数は返り値を返します。
3つの関数の返り値を取り出したい場合には、main関数を例えば次のように書きます。

#-------------------------#
# main func
if __name__ == '__main__':
    # - print p_input - #
    print(p_input)

    # - use function 1 - #
    ret = print_time_and_file_existence(p_input['FILE'])
    print(ret)

    # - use function 2 - #
    ret = print_hello_hogehoge(p_input['STR'])
    print(ret)

    # - use function 3 - #
    ret = calc_arithmetic(p_input['VAR1'], p_input['VAR2'], verb = False)
    print(ret)

“ret = function(hogehoge)”のように書くと、retという変数に返り値を格納することができます。
3つの関数の戻り値をretで受け取ってprintで表示しましょう。
関数3のverb引数はFalseにします。

このように編集してからhello_arithmetic.pyを実行すると以下のような結果になります。

図10. 返り値を表示するように編集した場合の実行結果

1つめと2つめの関数の戻り値は0なので、0が表示されています。
3つめの関数の戻り値は計算結果がリストに格納されています。



Conclusion | まとめ

最後までご覧いただきありがとうございました!
実際にPythonスクリプトを書いて、基本的な書き方に触れていただきました。

スクリプトをしっかり書けるようになると、Pythonで複雑な処理を実現したり、アプリを作ったりとさまざまなことができるようになります。
今回のプログラミングの内容自体はごく簡単なもので実戦的とは言えませんでしたが、処理を関数としてまとめてから呼び出すなど、スクリプトで実現できることのエッセンスが詰まっています。
これをきっかけとして更にPythonを学んでいきましょう!

以上、「python入門講座 | pythonを使ってみよう3-5(pythonスクリプトを書いてみよう)」でした!
またお会いしましょう!Ciao!

モバイルバージョンを終了