【入門者向け】Pythonの関数の実装|Python入門 #6

f:id:lib-arts:20190804170008p:plain

#1ではPythonを用いたFizzBuzzのコーディングについてまとめました。

入門者の方に読んでみていただいたところ、少し難しかったようなので、#2以降では#1で触れた基本文法をそれぞれもう少し丁寧に解説を行なっていきます。基本的には下記のPythonのドキュメントのチュートリアルなどを元にして解説していきます。

Python チュートリアル — Python 3.7.4 ドキュメント

#2ではPythonにおける四則演算・文字列について、#3ではリスト・タプル・辞書について、#4ではPythonの制御構文について、#5ではPythonの入出力に関して取り扱いました。

【入門者向け】Pythonの基礎文法① 四則演算・文字列|Python入門 #2 - lib-arts’s diary

【入門者向け】Pythonの基礎文法② リスト・タプル・辞書|Python入門 #3 - lib-arts’s diary

【入門者向け】Pythonの基礎文法③ 制御構文(if、for)|Python入門 #4 - lib-arts’s diary

#6ではSection4.6、Section4.7を中心にPythonの関数の実装について取り扱います。

4. その他の制御フローツール — Python 3.7.4 ドキュメント

以下目次になります。
1. 関数を定義する(4.6)
2. 関数定義についてもう少し(4.7)
3. まとめ


1. 関数を定義する(4.6)
関数とは入力になんらかの処理を施し、出力を行う箱のようなものだと考えるのが良いです。

f:id:lib-arts:20190828122615p:plain

数学における関数と同様で、単に入力に対応した出力を返すものとなっており、直感的には上図のイメージで捉えておければ十分です。

抽象的な話よりも実際に動かして見た方が早いので、早速下記を実行してみましょう。

def fib(n):   # write Fibonacci series up to n
    """Print a Fibonacci series up to n."""
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b

# Now call the function we just defined:
fib(2000)

上記はフィボナッチ数を計算する関数をプログラミングしています。実行結果は下記のようになります。

f:id:lib-arts:20190828164828p:plain

上記において、フィボナッチ数はx_{n+2}=x_{n+1}+x{n}という計算を行なっており、これは直前の二項の足し算で次の項を作成しています。これを実装するにあたって、aとbの二つの変数を用意し、それぞれに0と1を与え、随時値を置き換えて数列を生成しています。
ここまでがフィボナッチ数列の計算の実装の話ですが、ここからはPythonにおける関数の実装の話になります。関数の実装にあたっては定義する必要があるので、"def fib(n)"部分で関数の定義をしていることを明示しています。この説明ではわかりづらいと思うので、関数の必要性についてもっと詳しく見ていきましょう。
もともと上記のフィボナッチ数列を生成するプログラムは下記のように実装することができます。

a, b = 0, 1
n=2000

while a < n:
    print(a, end=' ')
    a, b = b, a+b

上記を実行すると同様に下記のようなフィボナッチ数列を得ることができます。

f:id:lib-arts:20190828165814p:plain

さて、なぜこのようにシンプルに実装することができるのに、わざわざ"def fib(n)"などを書いて行数を増やしてまで関数の実装を行ったのでしょうか。それは再利用性にあります。
例えば、2,000までのフィボナッチ数列を生成するという問題を解くだけなら関数を使わない実装で良いです。が、300、500、1,000、2,000、5,000、10,000までそれぞれ求める必要があるとなった場合はどうでしょうか。この際に関数を用いない実装だと、nの値を何度も変えてコピペのコードを実行する形になりなかなか見づらいです。

f:id:lib-arts:20190828170402p:plain

このようなコードは小規模で動かすうちは良いですが、段々と慣れてきたり後から見返したりする際に整理が難しくなります。ここで関数を使うと、下記のように実装できます。

f:id:lib-arts:20190828170738p:plain

このように関数を定義すると記述量を減らせたり、実装したコードの再利用性を高めたりすることができます。

関数の必要性についての説明はできたと思いますので、次に関数において重要となる引数と戻り値についてご紹介します。簡単に言うと、引数は関数の入力(Input)にあたり、戻り値は関数の出力(output)になります。引数の値に応じてなんらかの処理を行い、出力が必要な際は戻り値を返します。(関数内で処理を行い、戻り値は設定しない際もあります。


抽象的な話が続くと難しくなるので、こちらも書きコードを実際に動かしてみましょう。

def fib2(n): # return Fibonacci series up to n
    """Return a list containing the Fibonacci series up to n."""
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a) # see below
        a, b = b, a+b
    return result

f100 = fib2(100) # call it
print(f100) # write the result

実行結果は下記になります。

f:id:lib-arts:20190828172859p:plain

ここで関数名はfib2、引数はn、返り値はreturnの次に記述されているresultであることに注意です。
上記までで関数について一通り確認できたので、1節はここまでとします。


2. 関数定義についてもう少し(4.7)
2節ではSection4.7の内容を元に関数定義についてもう少し詳しく確認していきます。
関数の実装において可変個の引数を設定した上で定義を行うこともできます。引数の定義方法には3 つの形式があり、それらを組み合わせることが可能です。
・デフォルトの引数値(Section4.7.1)
デフォルトの引数値の説明に関してはドキュメントの説明がわかりやすいのでキャプチャします。

f:id:lib-arts:20190828173502p:plain

実装において引数の値のデフォルト値を"="を用いて設定することで、定義されている引数よりも少ない個数の引数で関数を呼び出すことができます。この書き方は便利なのと用いられているケースが多いので、最初から使いこなせなかったとしてもこういう機能があるとだけ抑えておくと良いかと思います。

 

・キーワード引数(Section4.7.2)
こちらもドキュメントの説明がわかりやすいのでキャプチャします。

f:id:lib-arts:20190828173926p:plain

上記のようにキーワード引数を用いて関数に引数を与える方法もあります。こちらもよく用いるので覚えておくと良いです。
また、詳しく説明するとわかりにくくなるのでしませんが、下記のように引数の実装を行うこともできます。

f:id:lib-arts:20190828174529p:plain

こちらについては実際に使用できる必要はないと思いますが、OSSのライブラリコードではこのような実装を見ることが多いので、見たな程度の認識だけ持っておいていただけると良いと思います。

 

・任意引数リスト(Section4.7.3)
あまり使わないとのことなので、下記の実行例だけ確認しておくと良いかと思います。

f:id:lib-arts:20190828174816p:plain


3. まとめ
#6では関数の説明やPythonにおける実装についてご紹介しました。
#7ではクラスについての概要とPythonでの実装について説明していきます。