第12章 関数について

12.1 関数の定義方法

Pythonではプログラミングを補助してくれる便利な関数「組み込み関数」が多数用意されています。
print、str、sum etc…

しかし、用意されている関数だけでは、やりたいことは行えないこともあります。そんな時は目的に応じた関数「ユーザー定義関数」を、自身で作成して利用すれば処理が行えるようになります。そんなユーザ定義関数を作ってから使うまでの方法を本章で学習して行きましょう。

12.1.1 ユーザー定義関数を作って使うまでの流れ

ユーザー定義関数を作って使うには、以下の2つの手順を行えばよいだけです。

① 目的に応じた関数を作成する(関数定義)
② 必要な場所で関数を呼び出す(関数コール)

組み込み関数は既に①が終わっている状態であるため、②から行うだけで関数を利用できました。しかし、ユーザー定義関数は自身で関数を作成する必要があります。また、ユーザー定義関数は以下のような場合に作ることが一般的です。

  • 組み込み関数に目的の処理が行えるものがない場合
  • 似たような仕組みの処理を何度も行っている場合
  • 規模が大きくなった処理を分割する場合

自身で関数を作成するのは大変かもしれませんが、1度作成しておけば関数は何度でも呼び出すことができるので、様々な場面で再利用することができるので大変便利になります。

関数を呼び出す場所を呼び出し元、呼び出される関数を呼び出し先と呼ぶこともあります。簡単に例えると呼び出し元が「会社の上司」となり、呼び出し先の関数は「部下」となります。上司は部下に命令して作業を行わせるように、関数も呼び出し元から、呼び出し先の関数をコールすることで処理を行わせることができます。
人は命令しなくても自分で考えて作業をこなすことができますが、プログラムでは命令しない限り処理は行ってくれません。関数を作って使うのは不便と思うかもしれませんが、逆に考えると人間は命令しても作業を行わない可能性がありますが、プログラムは命令した処理を絶対に行ってくれます。

図 12.1.1: 関数の動作は上司と部下の関係に似ている

12.1.2 ユーザー定義関数の作り方

ユーザー定義関数を作る方法は、以下の書式に従って行います。

書式:関数定義

関数には呼び出し元から情報を渡すことができますが、その情報のことを「引数(ひきすう)」といいます。また、逆に関数から情報を呼び出し元へ返すこともでき、その情報のことを「戻り値(もどりち)」といいます。
関数が処理を行う場合に、何か情報が必要であれば「引数」を設定します。さらに呼び出し元へ処理の結果などの情報を返す場合には「戻り値」の設定を行います。引数と戻り値は必ず設定するものではなく、関数の行う処理に応じて適宜設定する必要があります。

①def

プログラム内で関数を定義する場合に関数名より前に付けます。defとは「定義」の意味を表します。

②関数名

defの後ろに1文字の半角スペースを空けて、この関数の名前を任意で付けます。関数名は自由に付けることが出来ますが、以下の命名規則に従う必要があります。

  • 半角英数字と_(アンダーバー)が利用できる。但し先頭文字に数値は使えない。
  • 既にPythonが用意している関数の名前は使えない。(print、intなど)
  • 英字の大文字と小文字は区別されない。
③引数

関数へ渡す情報を受け取る変数を記述します。変数名は任意の名前で任意の数だけ設定できます。複数の引数を設定する場合は変数と変数の間を「,(カンマ)」区切って並べていきます。逆に1つも引数がない場合は、()の中には何も記述する必要はありません。

④コロン(:)

def、関数名、引数名が書かれた行末にはコロン(:)を書く必要があります。

⑤関数が行う処理

Pythonでは、明確に関数の処理が行われているブロックが明示されません。コロン(:)を記載したら改行をし、次の行から処理の内容を記載します。
処理内容が記載されたブロックの範囲は、インデントを元に判断するので、def、関数名、引数名が書かれた行より、インデントを一つ増やし、処理内ではインデントの幅を揃える必要があります。

⑥戻り値

関数内の処理中に「return文」を書くと戻り値が指定でき、returnの後ろに1文字以上の半角スペースを空けて戻り値を設定します。戻り値が不要な場合は、return文は省略します。
また、関数は1つでなく定義したい数だけ、いくつでも定義することができます。

書式:関数の呼び出し
	関数名( 引数 , … )
	

関数の呼び出しはとても簡単です、関数定義で付けた関数名と引数設定に応じた情報を設定して呼び出せばいいだけです。

①関数名

関数定義している関数の中で呼び出したい関数名を記述します。関数名は大文字、小文字を区別しませんが、基本は関数定義で付けた名前で呼び出します。

②引数

呼び出す関数に引数を渡す場合は、()内に記述します。但し、呼び出す関数に引数の設定がないと引数が渡せないので注意が必要です。引数が複数ある場合は渡す引数の間を「,(カンマ)」で区切ります。引数がない場合でも「()」だけは必ず記述します。

書式:戻り値を従える関数の呼び出し
	変数名 = 関数名( 引数 , … )
	

また、戻り値を受け取りたい場合は代入演算子と変数を設定するのが一般的ですが、不要な場合には省略することもできますし、戻り値が設定されていない場合には、変数へ受け取る処理は記述しません。

凡例:関数の定義と関数の呼び出し①

実行結果
	Hello world
	
凡例:関数の定義と関数の呼び出し②-引数を指定する場合
	def test2(name):
    	print(‘私は’,name,’です’)

	test2(‘鈴木’)
	
実行結果
	私は 鈴木 です
	
凡例:関数の定義と関数の呼び出し③-戻り値を指定する場合

実行結果
	2800
	
凡例:関数の定義と関数の呼び出し④-戻り値を指定する場合⑵

12.1.3 キーワード引数の利用

通常、複数の引数を使用した関数を実行する場合、関数で指定した引数の順番の通りに、引数を指定する必要があり、このような引数の指定方法を位置引数と呼びます。

凡例:位置引数の関数の出力例

	def name(last_name,first_name):
		full_name = '姓:'+last_name+',名前:'+first_name
		return full_name

	print(name('鈴木','太郎'))
	print(name('太郎','鈴木'))
	

実行結果

この凡例では、nameという関数を定義する際、last_name、first_nameの順番で引数を指定しているため、1回目の出力時first_nameには「鈴木」、last_nameには「太郎」が入り、「姓:鈴木,名前:太郎」が出力されますが、2回目はfirst_nameには「太郎」、last_nameには「鈴木」が入り、「姓:太郎,名前:鈴木」と姓と名前が反対の結果が出力されてしまいます。

図 12.1.2:位置引数への代入

この凡例のように位置引数の場合、引数に指定する場所を間違えると、望まない結果となる場合がありますので、こう言ったややこしさを解消するために、キーワード引数という引数の指定方法があります。

書式:キーワード引数による関数の値の取得方法

	def 関数名(引数名①,引数名②)
		処理内容…
		return

	変数名 = 関数名( 引数名① = 引数の値① , 引数名② =引数の値②… )
	

関数を呼び 出す際、定義時に指定された引数名と代入演算子を使って、特定の引数に値を代入する方法を、キーワード引数と呼びます。
直接、引数名を指定するため、位置引数と比べ、間違った引数に値を代入するといったミスを減らすことができます。

凡例:キーワード引数の関数の出力例

	def name(last_name,first_name):
		full_name = '姓:'+last_name+',名前:'+first_name
		return full_name

		print(name(last_name ='鈴木',first_name = '太郎'))
		print(name(first_name = '太郎',last_name ='鈴木'))
	

実行結果

		姓:鈴木,名前:太郎
		姓:鈴木,名前:太郎
	

この凡例の通り、キーワード引数を指定すれば、仮に順番が前後しても、位置引数のような順番が前後することによる想定と異なった値が出力されると言った事態が回避しやすくなります。

12.1.4 引数にデフォルト値を設定する

関数の定義時に、デフォルト(初期)値を設定することができます。デフォルト値が設定された引数には、何も代入しなければ、デフォルト値がそのまま格納され、値を代入した場合は、その値が代入されます。

書式:デフォルト値を設定した場合の関数の定義方法

	def 関数名(引数名①=デフォルト値①,引数名②=デフォルト値②)
		処理内容…
		return
	

凡例

	def name(last_name=’佐藤’,first_name=’次郎’):
		full_name = '姓:'+last_name+',名前:'+first_name
		return full_name

		print(name())
		print(name(last_name ='鈴木',first_name = '太郎'))
	

実行結果

	姓:佐藤,名前:次郎
	姓:鈴木,名前:太郎
	

この凡例では、1回目の関数name()を取得する際は、引数に値を何も代入しなかったため、そのままlasta_name、first_nameにはデフォルト値が格納されるので、「姓:佐藤,名前:次郎」が出力されます。
2回目の関数では、それぞれ引数に、last_nameには「鈴木」、first_nameには「太郎」を代入したため、「姓:鈴木,名前:太郎」が出力されます。

図 12.1.3:デフォルト引数の例

12.1.5 条件分岐を使用した関数の例

ソース・フォルダ:/Desktop/Python入門テキスト
ファイル名:第12章.ipynb
アクセスURL:http://localhost:8888/notebooks/Desktop/Python入門テキスト/第12章.ipynb

➢ 第12章.ipynb

	def num_to_day(num=0):
		#条件分岐開始
		if num == 0:
			day = '今日'
		elif num == 1:
			day = '明日'
		elif num == -1:
			day = '昨日'
		else:
			day = 'それ以外'
		return day
  
	print('引数なし:',num_to_day())
	print('引数1:',num_to_day(1))
	print('引数-1:',num_to_day(-1))
	print('引数2:',num_to_day(2))
	

実行結果

	引数なし: 今日
	引数1: 明日
	引数-1: 昨日
	引数2: それ以外
	

解説

今回のプログラムは、1~12行目が関数の定義部分になります。このnum_to_day関数は以下のように定義されています。
関数名:num_to_day
引数1:num
初期値1:0
戻り値:day

	def num_to_day(num=0):
		#条件分岐開始
		if num == 0:
			day = '今日'
		elif num == 1:
			day = '明日'
		elif num == -1:
			day = '昨日'
		else:
		day = 'それ以外'
	return day
	

この関数の内部では、条件分岐が指定されており、numの値によって、戻り値となるdayに格納される値が異なります。
13行目では、「num_to_day()」の関数を呼び出しており、引数numには何もしておりません。numには初期値である0が格納され、3行目の条件式を満たすため、4行目の処理が実行され、戻り値となるdayには「今日」が格納されるので、「引数なし: 今日」が出力されます。

	print('引数なし:',num_to_day())
	

図 12.1.4:関数num_to_day()の条件分岐

14~16行目に関しては、それぞれ引数numに1、-1、2を指定しています。

	print('引数1:',num_to_day(1))
 	print('引数-1:',num_to_day(-1))
 	print('引数2:',num_to_day(2))
	

14行目に関しては、「if num == 1:」を満たすため、戻り値dayに「明日」が代入され、「引数1: 明日」が出力されます。15行目に関しても、「if num == −1:」を満たすため、戻り値dayに「昨日」が代入され、「引数-1: 昨日」と出力されますが、16行目はどの条件式も満たさないので、「それ以外」が代入され「引数2: それ以外」が出力されます。

図 12.1.5:関数num_to_day()の条件分岐②

12.1.6 ラムダ式(無名関数)

ラムダ式とは無名関数と呼ばれている、名前を持たない使い捨ての関数です。定義した関数を再び使う必要がない、シンプルな関数を一時的に使用したい場合に便利です。

書式:変数を使用するケース

	変数1 = lambda 引数①,引数②: 式
	print(変数1(代入する値①,代入する値②,…))
	

ラムダ式は、変数に代入するのが一般的です。その場合、変数に代入した後に引数を指定するのが一般的です

凡例

	double = lambda num : num*2
	print(double(2)
	

実行結果

	4
	

図 12.1.6:変数を使用したラムダ式の例

また上記の凡例は、一般の関数を用いると以下のように書き換えることができます。

凡例:ラムダ式を関数に置き換えた場合

実行結果

	4
	

書式:変数を使用しないケース

	(lambda 引数①,引数②: 式)(代入する値①,代入する値②,…)
	

ラムダ式を何かの変数に代入せず、そのまま使用する場合、引数の値はどうするのかと言うと、設定しないと出力時にエラーが起きるため、括弧( )を使って引数の値を指定する必要があります。
また初期値が設定されている場合や、引数そのものを使用しないラムダ式においても、出力時には括弧()を使う必要があります。

凡例

	print((lambda num : num*2)(2))
	

実行結果

	4
	

凡例:引数に値を指定しない場合

	(lambda : print("hello"))()
	

実行結果

	hello
	

書式:初期値を利用するケース

	lambda引数① = 初期値,引数② = 初期値②,..  : 式
	

初期値を設定する場合は、このような書式で表します。先ほどお伝えした通り、初期値を設定されている引数に関しては、値を設定する必要はありませんが、出力時にはエラーが起きるので、()「括弧」を付け忘れないようにしましょう。

凡例

	(lambda x=5: print(x))()
	

実行結果

	5
	

12.1.7 ラムダ式を使用したプログラム

ソース・フォルダ:/Desktop/Python入門テキスト
ファイル名:第12章.ipynb
アクセスURL:http://localhost:8888/notebooks/Desktop/Python入門テキスト/第12章.ipynb

➢ 第12章.ipynb

	#変数numにラムダ式を代入
	num = lambda x=5: x*2

	#変数num1、num2を宣言
	num1 = num()
	num2 = num(10)

	print('初期値のままの場合:',num1)
	print('引数に代入した場合:',num2)
	

実行結果

初期値のままの場合: 10
引数に代入した場合: 20

解説

今回のプログラムは、2行目で変数numに、ラムダ式を代入しています。
引数1:x
初期値1:5
戻り値:x*2

	num = lambda x=5: x*2
	

numは変数ですが、事実上、numという名前の関数として使用することができます。5、6行目では新たに変数num1、num2を宣言しており、num1には引数xに値を設定しない(初期値のままの)numを代入し、num2には引数xに10を設定したnumを代入しています。

	num1 = num()
	num2 = num(10)
	

図 12.1.7:ラムダを使って変数に値を代入

8、9行目ではnum1、num2を出力しています。num1は引数に値を設定しないため、「初期値5×2 = 10」の値が格納されるので、8行目を実行すると「初期値のままの場合: 10」が出力され、num2は引数に10を設定しているため、「10×2 = 20」がnum2に格納されるので、8行目を実行すると「引数に代入した場合: 20」が出力されます。

	print('初期値のままの場合:',num1)
	print('引数に代入した場合:',num2)
	
ポイント
  • 関数は書式に従えば、自身で自由に作成することができる
  • 関数は引数と戻り値を任意で設定できる。
  • 関数は定義しただけではなく、呼び出して利用することで内部の処理を実行してくれる。
  • 関数は定義した引数の数に合わせて呼び出す必要がある。
  • 基本的に戻り値は代入演算子を使って変数に受け取るが、受け取りは任意で行える。
  • 関数内の変数と呼び出し元の変数は、同じ名前でも別々の変数として扱われる。

NEXT>> 12.2 変数の有効範囲