Python入門|関数の基本・関数作成時の書き方や利用方法

  • 公開日:2018/08/22
  • 更新日:2018/10/19
  • 投稿者:n bit

今回学習するのは関数です。いよいよプログラミングらしくなってきました。関数を覚えるとプログラムを記述するときにとっても楽をすることができます。

これまでの講座の中でも関数と言う言葉が出てきましたが簡易な説明のみで詳しくは解説してきていませんでした。まずは関数とは何かから解説していきましょう。

  • Python

この記事は約 分で読めます。(文字)

関数とは

関数と言う言葉は学生時代にも出てきましたよね。憶えていますか?数学が嫌いな人にとっては言葉を聞くだけで拒絶反応を起こすかもしれませんが本質はそんなに難しいものではありません。

関数の本質部分は

  • 「何かの入力を受けると、入力に対して特定の処理を行った出力結果を返す」

これだけです。

関数のイメージ

関数は解説の時にはよく身の回りの道具等に例えられますが、例えば冷蔵庫をイメージしてみてください。冷蔵庫に牛乳を入れたら牛乳を冷やしてくれますよね。これをプログラミング的に記述すると以下のようになります。

  • 『冷蔵庫』関数に『牛乳』を入力して、『冷えた牛乳』を出力結果として返す

つまり、冷蔵庫は何かの入力(牛乳)を受けると、特定の処理(冷やす)を行って出力結果(冷えた牛乳)を返す関数といえます。

このように関数は「何かの入力を受けると、入力に対して特定の処理を行った出力結果を返す」と言う仕事をしてくれるものです。

数学の関数も同じですね。例えば

  • \(y=x+3\)

と言う関数がありますが、これは入力値(x)に特定の処理(3を足す)を行った出力結果(y)を返しているだけです。

なんとなく関数のイメージは出来上がりましたか?

関数はどこで役に立つのか?

関数の中身は特定の実行処理を1つにまとめた小さなプログラムです。そのため関数は次のようなことに非常に役立ちます。

  • 1:繰り返し同じ機能を簡単に再利用できコード量が減る
  • 2:コードが機能毎にまとまり読みやすいプログラムになる
  • 3:コードのメンテナンス性が大幅に向上する

繰り返し同じ機能を簡単に再利用できコード量が減る

関数は特定の処理を返す道具となりますので同じような処理を何度も繰り返すシーンでとても効果を発揮します。実際に同じ処理を複数回繰り返すコードを、関数を使った場合と使わない場合で比較してみました。

サンプルで作成したコードはテキストデータを受け取るとその文字数をカウントして返すだけの単純な関数です。ここではコードの内容まで詳しく読む必要はありません。繰り返し同じ処理をするコードを記述したときに関数を使えばどれぐらいシンプルになるかを見てください。

関数を使用しない場合

x1 = 'たろう'

y1 = 0
for i in x1:
y1 += 1
print(y1)
x2 = 'さぶろう'
y2 = 0
for i in x2:
y2 += 1
print(y2)
x3 = 'ごろう'
y3 = 0
for i in x3:
y3 += 1
print(y3)

関数を使用した場合

def text_len(text):

length = 0
for i in text:
length += 1
return length

x1 = 'たろう'
print(text_len(x1))
x2 = 'さぶろう'
print(text_len(x2))
x3 = 'ごろう'
print(text_len(x3))

このサンプルでは全体のコードの長さが11行と15行でわずか4行しか変わりませんが、名前の長さを測る件数が増えるほど差はドンドンと広がるのです。例えば長さを測る件数が20件ある場合、45行と100行でその差は倍以上の開きが出ます。

コードが機能毎にまとまり読みやすいプログラムになる

もう一つのメリットは、役割ごとに関数化することでコードの内容を把握しやすくできることです。下記のサンプルコードは先程の文字数を測る関数とは別に受け取った数値が偶数か奇数かを判定しその結果を返す関数を追加しました。

def text_len(text):

length = 0
for i in text:
length += 1
return length

def even_or_odd(no):
if no % 2 == 0:
return '偶数'
else:
return '奇数'

x1 = 'たろう'
# 文字数を測る関数を実行
y1 = text_len(x1)
# 偶数か奇数かを判定する関数を実行
y1_eo = even_or_odd(y1)
print(y1_eo)h

関数化していることで各実行処理が1行で表記できるため、どこでどの処理を行っているかを把握しやすくなるのです。この効果は関数化できる処理が増えていくほど、コードの全体量が増えるほど大きくなります。

コードのメンテナンス性が大幅に向上する

プログラムは1度記述したらそれで終わりではありません。長期にわたり運用していると機能アップの時や不具合が出る都度コードの修正が必要です。そのためコードのメンテナンス性が高い事は必須事項といえます。

機能が関数に集約されているため機能内容を修正する場合は関数さえ変更すれば関数を使って処理を実行している所も全て一括で変更されます。

プログラミングのコードは出来る限り短い状態で目的とする処理を実行できれば理想的ですが、どうしても追加機能やイレギュラー処理への対応などを考え出すとコードは長くなりがち。

そのような場合にこの関数の3つのメリットは非常に有効的に働きます。最初のうちはどの実行処理をまとめて関数化すれば良いのかわかりにくいと思いますが、常に関数化することを考えながらコードを記述しいているとそのうち見えてくるもの。まずは意識することから始めましょう。

関数の記述方法

関数のイメージや役割が掴めたところで次は実際に関数をPythonコードで記述していきます。関数の記述方法は「def」を記述した後に任意の関数名をつけ『()』と最後に『:』(コロン)をつけて1行目が完成です。

2行目以下はインデントブロックを行い関数内で行う処理を記述していきます。

Python:関数の記述構造

関数名のルール

関数名の命名規則は下記の2項目に気をつけておいてください。

  • すべて小文字の半角英数字を利用する
  • 複数の単語をつなぐ場合はアンダースコア『 _ 』を利用する

引数

1行目関数名後の『()』内には関数内で扱われる引数を記述します。読み方は「ひきすう」。引数は関数内の実行処理で扱う値を指定するものです。括弧内にキーとなる変数名として指定します。

仮引数と実引数

引数は関数で定義する時と利用する時で呼び名が違います。定義するときには『仮引数』、利用するときには『実引数』。今回は説明用に厳密な名称をお伝えしていますが、実際の利用シーンではどちらも引数と覚えておけば充分でしょう。

仮引数:関数定義時(サンプルは:a)

def test(a):

print(a)

実引数:関数実行時(サンプルは:5)

関数を呼び出す時は関数名の後に『()』をつけて記述することで実行できますが、その『()』内に引数となる値を記述することで関数内に渡し処理することができるのです。

test(5)

仮引数のデフォルト値設定

関数定義時に仮引数を指定する方法は2種類あります。1つはデフォルト値を設定しない指定方法で、もう一つはデフォルト値を設定する指定方法です。

デフォルト値を持たない仮引数を指定する場合はキーとなる変数のみ記述、デフォルト値を持たす場合はキーとなる変数名と値をイコールでつなぎ記述します。

デフォルト値を設定しない場合

def test(a, b, c):

print(a)
print(b)
print(c)

デフォルト値を設定する場合

def test(a=0, b=1, c=2):

print(a)
print(b)
print(c)

仮引数がデフォルト値を持つ場合は関数実行時に実引数の指定を省略できますが、その時自動的に利用される値がデフォルト値です。デフォルト値を設定していない仮引数の場合は関数実行時に必ず実引数を指定する必要があります。

つまり、仮引数にデフォルト値を設定してない場合、自動的に関数実行時の必須実引数となりますので注意してください。

仮引数がデフォルト値を持つ場合は関数実行時に実引数を省略できる

def test(a=0, b=1, c=2):

print(a)
print(b)
print(c)

print(test())

出力結果

0

1
2

実引数の『位置引数』と『キーワード引数』

関数実行時に実引数を指定する方法も2種類。直接値だけを渡す方法と、キーと値を指定して渡す方法です。直接値だけを渡す方法を『位置引数』、キーと値を指定して渡す方法『キーワード引数』と呼びます。

位置引数:直接値だけを渡す方法

『位置引数』は名前の通り指定した位置によってどの仮引数に値を渡すかが決定されますので順序が重要となります。

def test(a, b, c):

print(a)
print(b)
print(c)

test(5, 10, 15)

出力結果

5

10
15

キーワード引数:キーと値を指定して渡す方法

キーワード引数の場合はキーを指定して値を渡しているため順序は問いません。

def test(a, b, c):

print(a)
print(b)
print(c)

test(c=15, a=5, b=10)

出力結果

5

10
15

仮引数がデフォルト値を持っているかどうかにかかわらず、実引数で位置引数、キーワード引数のいずれを渡しても大丈夫なのですが、一般的にデフォルト値を持たない仮引数には位置引数で、デフォルト値を持つ仮引数にはキーワード引数で渡していることが多く見受けられます。

位置引数とキーワード引数は混在させて指定することもできますが、その場合は必ず位置引数を指定した後にキーワード引数を指定するようにしてください。

def test(a, b, c, d=20, e=25):

print(a)
print(b)
print(c)
print(d)
print(e)

test(5, 10, 15, d=30, e=40)

出力結果

5

10
15
30
40

順序を逆にしてしまうと下記のようなエラーが出ます。

def test(a, b, c, d=20, e=25):

print(a)
print(b)
print(c)
print(d)
print(e)

test(d=30, e=40, 5, 10, 15)

出力結果

SyntaxError: positional argument follows keyword argument

引数にはこのほかにも少し特殊な指定方法がありますが、まずはこの基本的な指定方法をマスターしておけば大丈夫です。特殊な引数の指定方法については後のセクションで解説していきます。

戻り値

関数内で実行した結果を返すことができます。この値のことを『戻り値』と呼び、設定に利用するのは『return』です。『return』の後に戻したい値を指定することで結果として返すことができるようになります。

def test(a, b, c, d=20, e=25):

set_sum = a+b+c+d+e
return set_sum

y = test(5, 10, 15, d=30, e=40)
print(y)

出力結果

100

戻り値に指定できる形式

戻り値には様々なものを指定することが可能です。単体の値だけではなくリストや辞書等の形式でも返すことができます。

戻り値:リスト形式サンプル

def test(a, b, c, d=20, e=25):

set_list = [a, b, c, d, e]
return set_list

y = test(5, 10, 15, d=30, e=40)
print(y)

出力結果

[5, 10, 15, 30, 40]

戻り値:辞書形式サンプル

def test(a, b, c, d=20, e=25):

set_dict = {'a':a, 'b':b, 'c':c, 'd':d, 'e':e}
return set_dict

y = test(5, 10, 15, d=30, e=40)
print(y)

出力結果

{'d': 30, 'e': 40, 'a': 5, 'c': 15, 'b': 10}

return処理が実行されない場合はNoneが返される

関数内にreturn処理が用意されていない場合や、関数内で処理が途中で終わってしまいreturn処理が実行されなかった場合は自動的にNoneが戻り値として返ります。

Pythonのプログラミングにおいて戻り値を使った条件分岐などを行う場合がよくありますのでこの特性をおさえておきましょう。

関数内で利用する変数名について

関数内でも変数を利用することができますが、変数設定時のルールは通常の変数作成のルールと共通で関数内でもそのルールに従い変数名を自由に設定することができます。

関数内で変数『set_sum』を定義

def test(a, b, c, d=20, e=25):

set_sum = a+b+c+d+e
return set_sum

上記の様に関数内で設定する変数のことをローカル変数と呼び、関数の外で通常作られる変数はグローバル変数と呼ばれています。ローカル変数にグローバル変数と同じ変数名が使われる場合はいくつか注意点がありますので気をつけましょう。

グローバル変数を関数内で呼び出すとグローバル変数で代入されている値が参照できます。呼び出す事はできるのですが値を代入しなおすことはできません。そのまま呼び出した場合は値の参照のみが可能です。

関数内でグローバル変数『set_sum』を参照

set_sum = 300



def test(a, b, c, d=20, e=25):
print(set_sum)

test(5, 10, 15, d=30, e=40)

出力結果

300

下記のようにグローバル変数に代入処理を行った場合はエラーが出力されます。

set_sum = 300



def test(a, b, c, d=20, e=25):
print(set_sum)
set_sum = a+b+c+d+e
return set_sum

test(5, 10, 15, d=30, e=40)

出力結果

UnboundLocalError: local variable 'set_sum' referenced before assignment

これは関数内でグローバル変数に代入を行うとローカル変数として新規に定義しようとするため代入前に呼び出していたグローバル変数が未定義のローカル変数扱いになりエラーとなるためです。

ローカル変数ではグローバル変数と被る変数名を利用しないようにするか、グローバル変数は読み込み専用と考える、もしくは、ローカル変数定義時に必ず最初に変数の初期化を行っておくことでエラーは回避できます。

関数内でグローバル変数の書き換えまで行いたい場合はグローバル変数の前に『global』を記述し
グローバル変数として関数内で先に宣言する必要があります。

関数内でグローバル変数『set_sum』に代入

set_sum = 300



def test(a, b, c, d=20, e=25):
global set_sum
print(set_sum)
set_sum = a+b+c+d+e
return set_sum

y = test(5, 10, 15, d=30, e=40)
print(y)
print(set_sum)

出力結果

300 # print(set_sum)

100 # print(y)
100 # print(set_sum)

関数内でグローバル変数として定義したため関数内でグローバル変数set_sumに代入することができました。そのため関数実行後はグローバル変数set_sumに代入されている値が100に変更されているのが確認できます。

グローバル変数とローカル変数の概念は慣れるまで少し難しいと思いますので、最初のうちは出来る限り変数名を分けるようにしておくと理解しやすいでしょう。

またグローバル変数として宣言し値を代入し直すよりは引数で関数内に値を渡し処理した後、戻り値で返した方が汎用性の高い関数となります。

今日のdot

Pythonプログラミングにおいて関数の定義は非常に重要なセクションです。慣れるまでは色々とつまずくことも多いと思いますが、このページの内容確認しながら色々と関数化してみましょう。

機能としてパッケージ化できるものの判別や、パッケージ化した機能に必要な値などが徐々にわかるようになってきます。そうなれば関数のコード構造も明確になるので、まずは関数化してみようとする意識が重要です。

▲ ページの先頭へ戻る

このページの目次

目次