5. 関数

関数 は、定められた一連の処理に名前をつけてまとめて、その名前を使って処理を呼び出すことができる仕組みです。
Pythonでは主にdef文で関数を定義します。
関数を使うことで、同じ処理を何度も書く必要がなくなり、プログラムを簡潔に書くことができます。

関数の定義(関数を作る)

関数を作ることを「関数を定義する」といいます。
関数の定義には、以下のようにdefキーワードを使います(defは「define(定義する)」の略)。

def 関数名():
	処理1
	処理2
	...

関数に含める処理(関数の「内部」)は、関数名の次の行からインデントして記述します。関数名は、その関数が何をするかを表す名前を、変数名と同じように自由につけることができます。

例として、与えられた2つの数字の和を求める関数addは以下のように定義できます:

def add(num1, num2):
	result = num1 + num2
	return result

作成するadd関数には、「与えられた2つの数字の和を求める」処理をしてもらいたいため、まず関数に2つの値を渡す必要があります。関数では、関数で利用するために必要な情報を引数として受け渡すことができます。引数は、関数名の後ろの丸括弧()の中に,区切りで記述し、関数内で変数のように利用することができます。引数の数は任意であり、0個でも3個以上でも構いません。

例のadd関数では、足し合わせて欲しい2つの数字をnum1num2という引数で受け渡すようにしています。(※引数の名前も、変数名と同じように自由につけることができます。)

例えば、num1 = 3num2 = 5になるように値を渡してあげると、関数の内部ではresult = 3 + 5が計算され、resultには8が代入されます。

しかし、このresultという変数は、あくまでも関数の内部(インデントされている箇所)で作成した変数であり、このままでは関数の外から足し合わせた結果を使う(変数に代入したり、print関数で出力したりする)ことができません。なぜなら、Pythonではインデントした箇所内で初めて宣言した変数を、インデント以外の場所から参照することができないためです。そこで、関数の外から関数内で作成した変数を参照するためには、return文を使って関数の外に返す必要があります。関数では、return 文を使って return 返す値 という形で関数の外に値を返すことができます。

例のadd関数では、resultreturn文で返しています。これにより、関数addを呼び出した時に、足し合わせた結果を外から使うことができます。

関数の呼び出し(関数を使う)

関数を使うことを「関数を呼び出す」といいます。
関数を呼び出すには、関数名の後ろに丸括弧()をつけ、必要であれば引数を渡します。

関数がreturn文を使って何かを返す場合、その返り値をそのまま変数に代入したり、print関数で出力したりすることができます。

例のadd関数を呼び出すには、以下のようにします:

例題1
def add(num1, num2): # add関数を定義
	result = num1 + num2
	return result

a = 3
b = 5
c = add(a, b) # add関数を呼び出し、結果をcに代入
print(c) # 8が出力される

add(a, b)は、add関数にa(3)とb(5)を渡して呼び出す処理です。この処理を実行すると、引数に順番にnum1には3num2には5が代入され、関数内でresult = 3 + 5が計算されます。その後、resultの値である8が返され、cに代入されます。

もし、return句がない場合、関数は何も返さないため、resultには適切な計算結果が代入されず、代わりに「値が存在しないことを表す」というNoneという特別な値が代入されます。

def add(num1, num2): # add関数をreturn無しで定義
	result = num1 + num2

c = add(3, 5) # add関数を呼び出し、結果をcに代入。しかし何も値が返されないため、cにはNoneが代入される
print(c) # Noneが出力される

定義と呼び出しの注意点

関数を作ると何が嬉しいのか?

例えば、以下のようにある処理Aを3箇所で利用するようなコードがあるとします。

処理A

... # 何らかの別の処理

処理A

... # 何らかの別の処理

処理A

もし、処理Aに変更があった場合、それぞれの処理Aを変更する必要があります。手作業で一つずつ変更するのは手間がかかりますし、変更忘れなどのミスも発生しやすいです。

処理A # ←変更があると...... (変更箇所1)

...

処理A # ←ここも変更が必要(変更箇所2)

...

処理A # ←ここも変更が必要(変更箇所3)

一方、処理Aを関数として定義する(例えば、process_Aという名前で関数にする)と、コードは以下のようになります。(※processは「処理」の英語表現 )

def process_A():
	処理A

process_A()

...

process_A()

...

process_A()

この場合、処理Aに変更があった場合、process_A関数の中身だけを変更すれば良いので、コードの修正が簡単になります。作業効率の向上に加え、変更漏れやミスのリスクも減らすことができます。

def process_A():
	処理A # ←変更があっても......(変更箇所1)

process_A() # ←ここは変更不要

...

process_A() # ←ここも変更不要!

...

process_A() # ←ここも変更不要! 

# → 総じて、変更箇所が3箇所から1箇所に減りました!

また、関数には、その関数が何をするかを表す名前をつけることができます。そのため、関数を使うことで、コードが何をしているのかが一目でわかりやすくなります。複雑な数式や、複数行にわたる処理を一つの名前で表すことができるので、コードが読みやすくなります。

まとめ

関数は、定められた一連の処理に名前をつけてまとめ、その名前を使って処理を呼び出すことができる仕組みです。
Pythonでは主にdef文で関数を定義します。

def 関数名():
	処理1
	処理2
	...

関数には、関数内で利用するために必要な情報を引数として受け渡すことができます。関数がreturn文を使って何かを返す場合、その返り値をそのまま変数に代入したり、print関数で出力したりすることができます。

問題1

三角形の面積は「底辺 ✕ 高さ ÷ 2」(英:Area of a triangle = base × height ÷ 2)で求められます。
この計算を行う関数triangle_areaを定義し、底辺baseと高さheightを引数として受け取り、三角形の面積を返す関数を作成します。
以下のプログラムを実行し、底辺が4、高さが3の三角形の面積を得るために「ア」「イ」「ウ」に当てはまる適切な回答の組み合わせを選び、プログラムを完成させてください。

def triangle_area(「ア」):
	area = base * height / 2
	「イ」 area

a = 4
b = 3
c = triangle_area(「ウ」)
print(c) # 6が出力される

答え:ア:base, height、イ:return、ウ:a, b

関数内で仮引数baseheightを使い、グローバル変数abを引数として渡しています。また、関数内で計算された面積をreturn文で返します。なお、「ア」と「ウ」の変数の組み合わせが逆であると、関数内で宣言されているローカル変数baseheightを、7行目(関数の外)で渡すこととなり、呼び出しの際に参照できずエラーが発生してしまいます。

問題1
def triangle_area(base, height):
	area = base * height / 2
	return area

a = 4
b = 3
c = triangle_area(a, b) # base = 4, height = 3として関数を呼び出し、結果をcに代入
print(c) # 6が出力される