どうも! 職業訓練製のがっちゃんです!
50歳にして長期人材育成「情報セキュリティ管理者資格」2年コースを絶賛受講中です!
今回は、授業で習った「Python3系」プログラミングの基礎:関数編として書いていきたいと思います。
プログラミングで使用したソフトは「Anaconda」というパッケージソフトの「Spyder4」というアプリを使って勉強しました。
関数:def
プログラミングでの命令や処理をひとまとめにしたものを関数と言います。pythonではdefに続いて関数を宣言します。自動販売機の「お金を入れてから飲み物が出てくる一連の処理」や「どんな数字も2倍にする不思議な箱があって、そこに2を入れると4になる」箱自体が関数ですね。
関数を利用する理由は、1:関数で処理したいプログラムをまとめられるので、同じプログラムコードを書かなくて済む。2:プログラムの見通しがよくなるので、プログラムが分かりやすくなる。3:エラーが見つけやすくなる、と言ったところでしょうか。
実行した結果、何か値を生み出す関数と何も生み出さない関数があります。実行した結果を return した場合、値は戻り値として関数を呼び出した命令に返ってきます。
戻り値がない関数
画面に出力する変数や配列、その他のオブジェクトを変更するなど、呼び出し元に実行結果を戻さない関数です。
例えば、ATMで口座に入金するのは、戻り値のない関数といえます。関数処理はきちんと行われるので、口座の残高は増えますが、手元にはなにも出てこないですよね。え!?カードと通帳は出てくるって!?それはまた別の話です。
戻り値がない関数の書き方は以下のとおりです。return 処理がないことが分かりますね。
1 2 3 |
def 関数名( ): 処理 関数名( ) ←関数の呼び出し |
実際にプログラムを書いて動きを見てみましょう。
※注意:最後に関数の呼び出しを書かないと、プログラムエラーになります。気を付けてください。
まずは、引数がない関数です。show_name という関数を宣言し、()には本来引数が入りますが、省略しました。
こちらは、nameという引数を与えています。この引数に、最終行で「gacchan」という名前を代入して呼び出しています。ちなみに引数は文字でも文字列でも数字でも、なんでも代入することができます。
こちらが実行結果で「gacchan」という名前が表示されます。二つのプログラムは同じ実行結果になります。戻り値がありませんので、再利用することはできません。再利用する予定がある場合は戻り値を返す return を使いましょう。
次は2つの仮引数を準備してプログラムを作成します。ここで注意しないといけないのが、ageの型です。print(type(age))で、ageの型を調べると、以下の実行結果のとおり、int型ということが分かります。pythonの場合、int型をプリントさせようとするとstr 文字列型に変換させる必要があります。ここは、javaやってると( ,,`・ω・´)ンンン?ってなっちゃいますよねぇ。気を付けましょう。
戻り値がある関数
ATMで口座から現金を引き出すのは、戻り値がある関数です。戻り値がある関数には、return が付いてきます。戻り値のある関数は、実行結果を受け取る必要があるので、実行結果を変数に格納するか、別の関数の引数に設定するなど、処理を引き継ぐ必要があります。
1 2 3 4 |
def 関数名(引数1, 引数2・・・): 処理 return 戻り値 関数名(引数1, 引数2・・・) ←関数の呼び出し |
実行結果は以下のとおりです。
と、授業で教えてもらったのですが、なんか書き方がしっくりこないんですよねぇ。で、こんな風に書き換えました。
実行結果は以下のとおり、授業で教えてもらったプログラムと同じ結果。
ま、好みでどちらでもどうぞ、というところでしょうかね。
Python独特のキーワード引数
位置で引数の指定もできますが、x,yなど、キーワードで引数を指定することもできます。以下のプログラムは、キーワードで引数を指定したものと、位置で引数を指定したものの2種類を実行させてみました。
実行結果は以下のとおりです。
キーワードで引数を指定した場合、以降の引数もすべてキーワードで引数を指定してあげないと以下のようにエラーになってしまいます。
でも、こんなふうに引数を指定してあげれば、一応「キーワードで引数を指定した以降はキーワード指定している」のでセーフです。ってか、「10はxだよね」って位置で判断できているものね。だから、最後の z を x にしちゃうとエラーになっちゃいますね。
引数のデフォルト値
関数を定義するときに、引数のデフォルト値(初期値)を設定する方法です。事前に設定しておけば、関数宣言時に引数の値を指定しなくても、デフォルト値を利用して処理してくれます。以下のプログラムでは、消費税率だけデフォルト値で1.1に設定しています。
また、以下のように呼び出し時に引数を指定すると、そちらを優先してプログラムが実行されます。
可変長引数
引数の手前に「*」「**」を付けると、呼び出し時に任意の引数を指定することができます。「*」は、タプル・リスト型「**」は、辞書型(=の左側をkey、右側をvalueとして展開されます)で受け取ります。
以下のプログラムのように、普通は3つの引数が必要ですが、1つの引数で指定できていることが分かると思います。
特に名前、住所、電話番号などの似たような属性値を扱うときに便利です。
モジュール化
Pythonでは、複数の関数を1つのファイルにまとめたものを「モジュール」と言います。「import」メソッドを使用することでプログラムに呼び出し、利用することができます。
まずはいつものように、同じファイル上に関数を使ってプログラムしていきます。名前を出力する関数と、三角形の面積を出力する関数の2つを書きました。
これを、名前を出力する関数と、三角形の面積を出力する関数を「def1.py」というファイルにモジュール化します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# -*- coding: utf-8 -*- """ Created on Sat Aug 8 12:00:12 2020 @author: kazen """ # モジュール化 # 複数の関数をひとまとめにしたファイルのこと # 名前を出力する関数 def show_name( x ): print ( "私の名前は" + x + "です!") # 三角形の面積を出力する関数 def calc_triangle ( base, height ): area = base * height / 2 return str ( area ) # 実行結果を出力 show_name ( "gacchan" ) print ( calc_triangle(10, 8)) |
で、こちらが実行を呼び出すメインのプログラム「main.py」です。
1 2 3 4 5 6 7 8 9 10 |
# -*- coding: utf-8 -*- """ Created on Sat Aug 8 12:01:29 2020 @author: kazen """ # def1.pyモジュールの呼び出し import def1 # 名前を出力する関数と三角形の面積を出力する関数に引数を渡して実行 def1.show_name('gacchan') print (def1.calc_triangle( 100, 50 )) |
上の「main.py」プログラムの実行結果がこちら。実行結果が2つ出てますね。原因は「def1.py」にも、それぞれの関数を出力するプログラムが残っていたので、一緒に出力されています。
「def1.py」の出力プログラムのところだけ消しても解決するのですが、授業では、以下のように「main.py」が実行されているときは、こっちのは実行しないようにしてね!というプログラムにしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# -*- coding: utf-8 -*- """ Created on Sat Aug 8 12:00:12 2020 @author: kazen """ # モジュール化 # 名前を出力する関数 def show_name( x ): print ( "私の名前は" + x + "です!") # 三角形の面積を出力する関数 def calc_triangle ( base, height ): area = base * height / 2 return str ( area ) # main.pyが実行されているときにこちらを実行しないようにする定型文 # main.pyが実行されているなら、以下の実行はしないでね。 if __name__ == "__main__": # 実行結果を出力 show_name ( "iguchi" ) print ( calc_triangle(10, 8)) |
そして、再度「main.py」を実行すると、以下のように、「main.py」のみ実行されているのが分かります。
特定の関数だけを借りてくる
特定の関数「show_name」だけ借りてくるimportメソッドの書き方は、以下のとおりになります。
1 2 |
# def1.pyからshow_name関数を借りてきます from def1 import show_name |
特定ディレクトリにある関数を呼び出すとき
今までは同じディレクトリ内にあるモジュールを呼び出す方法でした。別のディレクトリにあるモジュールを呼び出すときはいかのようにimportメソッドを書きます。
※例として「func」フォルダ内のモジュールを呼び出す場合を書きます。
1 2 |
# func ディレクトリになるdef1.pyモジュールを呼び出します。 from func import def1 |
練習問題1:「文字あてゲーム」を関数をつかって作成、モジュール化する
Pythonプログラミングの基礎:その1(制御文)のブログで作成した「文字あてゲーム」を関数を使って作成、モジュール化していきます。以前作成した「文字あてゲーム」プログラムを見たい方は、以下のブログをご参考ください。
まずは「mojiate.py」を関数を使って作成していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# -*- coding: utf-8 -*- """ Created on Sat Aug 8 16:05:26 2020 @author: kazen """ # 文字あてゲーム2(関数を使ってプログラムする) """ リストに文字を用意します キーボードから一文字入力してもらい 文字がリストに含まれているかどうかを判定する """ # ゲーム開始を表示 print("文字あてゲーム始まるよ~(*^-^*)") print("リストの中に入っているアルファベット(大文字)を当ててみて!") print("1文字でいいよ!") # リストの準備 moji_list = ["A", "C", "H", "L", "O", "Q", "T", "V", "Y", "Z" ] print(moji_list) # 文字を1つ入力してもらい moji 変数に格納 moji = input("リストの中に入っている文字は、なぁ~んだ!?:") # 正解不正解を確認する関数 def judge( moji, moji_list): # judgement の初期値をFalseに設定 judgement = False # 正解・不正解の判定 if moji in moji_list: judgement = True return judgement # 結果を表示する関数 def show_judge( judge ): if judge: print("やったぜ!正解!") else: print("その数字は入ってないYO!") # 判定結果を出力 show_judge ( judge( moji, moji_list) ) |
実行結果は以下のとおりです。キチンとできてますね。
次は、関数をモジュール化して別ファイル「game_module.py」に格納します。「game.py」で関数を呼び出しプログラムを実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# -*- coding: utf-8 -*- """ Created on Sat Aug 8 16:25:05 2020 @author: kazen """ # judge 関数と show_judge 関数をモジュール化 # 正解不正解を確認する関数 def judge( moji, moji_list): # judgement の初期値をFalseに設定 judgement = False # 正解・不正解の判定 if moji in moji_list: judgement = True return judgement # 結果を表示する関数 def show_judge( judge ): if judge: print("やったぜ!正解!") else: print("その数字は入ってないYO!") |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# -*- coding: utf-8 -*- """ Created on Sat Aug 8 16:26:48 2020 @author: kazen """ # game_module.pyをインポート from game_module import show_judge, judge # ゲーム開始を表示 print("文字あてゲーム始まるよ~(*^-^*)") print("リストの中に入っているアルファベット(大文字)を当ててみて!") print("1文字でいいよ!") # リストの準備 moji_list = ["A", "C", "H", "L", "O", "Q", "T", "V", "Y", "Z" ] print(moji_list) # 文字を1つ入力してもらい moji 変数に格納 moji = input("リストの中に入っている文字は、なぁ~んだ!?:") # 判定結果を出力 show_judge ( judge( moji, moji_list) ) |
「game.py」を実行した結果がこちらになります。
どうですか!?うまく実行できましたか!?実際モジュール化をやってみて分かると思いますが、これくらいのプログラムでモジュール化しても、手間がかかるばっかで大変ですよねぇ。なんでこんなことするんだろ!?というのがホンネのところ。
でもでも、もっと大規模なシステム開発やゲーム開発だと、「君はここのモジュールやってね」「あなたはここのモジュールね」とチームで役割分担してプログラミングができることが分かると思います。ついでに「このプログラムモジュール作ったん誰!?」と責任の所在もしっかり分かると言うものですね。
組み込み関数
インポートや定義なしに利用できる関数のことです。今までひんぱんに使っているprint関数も組み込み関数の1つです。標準で用意されている関数で、特別な設定を行わなくても自由に呼び出して利用することが可能です。以下にPython公式ページのライブラリを紹介しておきますので、いろいろな組み込み関数があることを確認してみてください。
せっかくなんで、ちょっとだけ練習。最小値、最大値、配列のソートをしてみます。
random関数
ランダム関数は、なにが生成されるかわからない数字、乱数を生成することができます。
random関数を使用するにはrandomモジュールをインポートする必要があります。プログラムの最初に「import random」と書くことでモジュールがインポートされます。簡単ですね。
0~1までの乱数を生成:random.random()
整数をランダムに生成:random.randint()
リストの中の文字をランダムに出すのも、この「random.randint」を使用します。「random.randint(x, y)」のx,yにより、リスト内のどこからどこまでを対象範囲にするかを決めることができます。以下のプログラムでは全てを選択していることになりますが、「tue」から「fri」までを対象範囲にする場合は(2,5)とします。※1からではなく0から始まるので対象範囲の選択にはご注意ください。
特にリスト内の範囲指定が不要なら「random.choice()」を使います。
リスト内をシャッフルするには「random.shuffle()」を使います。
format関数
文字列内に変数を埋め込むことができます。文字列内で動的に変化する変数を利用して表示させることが可能になります。書き方は次のように書きます。
1 2 |
"任意の文字列{}任意の文字列”.format(変数) "{}任意の文字列”.format(変数) |
実際にプログラムにして実行してみると一目瞭然です。
上のが通常よく使われる書き方です。授業では、以下のようなformat関数の使い方も習いました。
3ケタごとにカンマを付ける
数字をバイト変換
文字列に指定された文字を入れる
練習問題2:抜けているアルファベットを当てるプログラムを作成する
それでは、今回の関数編の総復習として、「抜けているアルファベットを当ててみよう!」というプログラムを作成してみます。
まずは関数なしで普通にプログラミング
最初から関数で書いて、モジュール化して、とか考えるとなかなか手が付けられません。まずは、コメントアウトでプログラムのストーリーを書いていき、普通に関数なしでプログラムを作ってみましょう。途中途中でprint分をはさんで、出力結果が合っているかを確認すると、プログラムミスがなくなりますよ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# -*- coding: utf-8 -*- """ Created on Sat Aug 8 18:40:02 2020 @author: kazen """ # 抜けているアルファベットを当ててみよう # ゲーム開始、ルールの説明 print ( "AからGまでのアルファベットがあります。" ) print ( "抜けているアルファベットが1つあるので、その文字を当ててください!") # アルファベットのリストを準備する alphabets = ["A", "B", "C", "D", "E", "F", "G"] # シャッフルでアルファベットをひとつ抽出 import random random.shuffle(alphabets) # print ( alphabets ) # 抽出したアルファベットを正解とする answer = random.choice(alphabets) # print ( answer ) # 結果判定のための変数を準備 result = False # 正解を抜いたアルファベットの文字列を出力 questions = "" for a in alphabets: if a != answer: questions += a print ( questions ) # 抜けているアルファベットの文字を入力してもらう players_input = input( "抜けているアルファベットを入力してみて!:") # 正解か不正解かの結果を出力 # upper()メソッドで小文字を入力しても大文字扱いにする if players_input.upper() == answer: print ( "やったね!正解!") else: print ( "残念!間違い!正解は" + answer + "ですわぁ~" ) |
入力出来たら実行してみましょう。実行結果は以下のとおりです。うまく実行できましたか!?これまだAからGまでなので、簡単に回答できますが、もっとアルファベットの数を多くすると難易度はグン!とアップしますので、アルファベットのリストを作り変えて実行してみてください。
次は関数を使ってプログラムを作成
次は、上のプログラムをベースに、関数を使ってプログラミングしていきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# -*- coding: utf-8 -*- """ Created on Sat Aug 8 19:03:00 2020 @author: kazen """ # 抜けているアルファベットを当ててみよう(関数を使った改良版) # アルファベットのリストを準備する(さっきより難易度を上げるためたくさん用意した!) alphabets = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", ] # ゲーム開始、ルールの説明を関数化 def show_rules( alphabets ): print ( "{}から{}までのアルファベットを表示します。".format(alphabets[0],alphabets[-1]) ) print ( "抜けているアルファベットがあるので、その文字を当ててください!") show_rules(alphabets) # シャッフルでアルファベットをひとつ抽出 import random random.shuffle(alphabets) # print ( alphabets ) # 解答の選出(抽出したアルファベットを正解とする) answer = random.choice(alphabets) # print ( answer ) # 正解を抜いたアルファベットの文字列出力を関数化 def make_question(): questions = "" for a in alphabets: if a != answer: #ランダムで数字を作って1なら小文字にする r = random.randint( 0, 1 ) if r == 1: a = a.lower() questions += a return questions print ( make_question() ) # 回答:抜けているアルファベットの文字を入力してもらう players_input = input( "抜けているアルファベットを入力してみて!:") # 判定:正解か不正解かの結果出力を関数化 # upper()メソッドで小文字入力でも大文字扱いにする def judge(players_input, answer ): if players_input.upper() == answer: print ( "やったね!正解!") else: print ( "残念!間違いです!正解は{}です".format( answer )) judge ( players_input, answer ) |
プログラム出来たら実行してみましょう。アルファベットリストに全部のアルファベットを使ったうえにランダムで大文字小文字にして出力させるようにしたので、クイズの難易度が格段に上がっています。実行結果は以下のとおりです。正解を見つけるのに20秒くらいかかりましたわ。
関数をモジュール化
最後の仕上げです。さきほど作成した関数を「mojiate5_module.py」にモジュール化、モジュールを呼び出すプログラムを「mojiate5.py」で作成し、実行させてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# -*- coding: utf-8 -*- """ Created on Sat Aug 8 19:17:26 2020 @author: kazen """ import random # ゲーム開始、ルールの説明を関数化 def show_rules( alphabets ): print ( "{}から{}までのアルファベットを表示します。".format(alphabets[0],alphabets[-1]) ) print ( "抜けているアルファベットがあるので、その文字を当ててください!") # 正解を抜いたアルファベットの文字列出力を関数化 def make_question( alphabets, answer ): questions = "" for a in alphabets: if a != answer: #ランダムで数字を作って1なら小文字にする r = random.randint( 0, 1 ) if r == 1: a = a.lower() questions += a return questions # 判定:正解か不正解かの結果出力を関数化 # upper()メソッドで小文字入力でも大文字扱いにする def judge(players_input, answer ): if players_input.upper() == answer: print ( "やったね!正解!") else: print ( "残念!間違いです!正解は{}です".format( answer )) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# -*- coding: utf-8 -*- """ Created on Sat Aug 8 19:17:08 2020 @author: kazen """ # mojiate5_module.pyの呼び出し from mojiate5_module import show_rules, make_question, judge # 抜けているアルファベットを当ててみよう(関数をモジュール化した改良版) # アルファベットのリストを準備する(さっきより難易度を上げるためたくさん用意した!) alphabets = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", ] # ゲーム開始、ルールの説明の関数を呼び出し show_rules(alphabets) # シャッフルでアルファベットをひとつ抽出 import random random.shuffle(alphabets) # print ( alphabets ) # 解答の選出(抽出したアルファベットを正解とする) answer = random.choice(alphabets) # print ( answer ) # 正解を抜いたアルファベットの文字列出力の関数を呼び出し print ( make_question( alphabets, answer ) ) # 回答:抜けているアルファベットの文字を入力してもらう players_input = input( "抜けているアルファベットを入力してみて!:") # 判定:正解か不正解かの結果出力の関数を呼び出し judge ( players_input, answer ) |
さて、うまくモジュール化できましたでしょうか!?実行結果はこちらになります。ゲームの難易度は先ほどと同じです。私はちょっと見慣れたからでしょうか、先ほどより早く回答できるようになりました!
まとめ
今回のPythonの基礎:関数編、いかがでしたでしょうか!?モジュール化で、チーム開発ができることが分かり、ちょっとプログラミング中級者の仲間入りを果たしたような気がしませんか!?私はもうプログラミング中級者になった気分ですよ!今年の基本情報技術者試験のプログラミングは俄然、Pythonで挑んでみようという気になりましたよ。
おっとその前に、基本情報技術者試験のシラバスでPythonの技術がどれくらい必要なのかを確認してみよう。以下、IPAが公表しているシラバスからの抜粋です。
(4)Python の知識と技術
【小目標】
Python のプログラムの作成方法の基本を修得し,適用する。
オブジェクトの生成方法,操作方法を修得し,適用する。
問題解決のために適した代表的な標準ライブラリ又は外部ライブラリを用いて,効率良くプログラミングを行う方法を修得し,適用する。
数値計算,テキスト処理,データ処理などを行うプログラムの作成方法を修得し,適用する。
インタプリタであることの長所と短所を理解して利用する方法を修得し,適用する。
① Python の基本的なプログラム
Python の基本的なプログラムを作成する。
修得項目 インデントによるブロック表現,計算結果の表示,コメント など
② 演算子を用いた式の表現
四則演算や論理演算を用いた式を活用し,プログラムを実行モードや対話モードで利用する。
修得項目 整数,浮動小数点,式の表現,四則演算子,代入演算子,比較演算子,論理演算子,代入文 など
③ 要素をもつデータ型
シーケンスなど,要素をもつデータ型を使ったプログラムを作成する。
修得項目 in,リスト,文字列,タプル,辞書,集合,イテレータ,添字,キー,スライス,リスト内包表記 など
④ 選択型のプログラム
条件式を使って条件分岐するプログラムを作成する。修得項目 if 文 など
⑤ 反復型のプログラム
反復型の制御文を使ったプログラムを作成する。
修得項目 for 文,while 文 など
⑥ 組込み関数
型,リスト,文字の入出力,ファイル操作などに関する組込み関数の利用場面を理解し,プログラムを作成する。
修得項目 int,float,str,list,range,enumerate,zip,len,print,input,open など
⑦ 関数の定義
利用者の定義による関数を用いて構造化されたプログラムを作成する。
修得項目 def 文,return 文,ジェネレータ,yield 文,ラムダ式,再帰呼出し,デコレータ など
⑧ クラスとオブジェクト
クラスを定義し,オブジェクトを生成してプログラムを作成する。
修得項目 クラス,オブジェクト,class 文,継承,クラス変数,メソッド,特殊メソッド__init__ など
⑨ 変数及び関数の値の取扱い
変数間の代入,オブジェクトの変更,関数の値の受渡しに注意し,プログラムを作成する。
修得項目 変数のスコープ,変更可能なオブジェクト,コピー,位置引数,キーワード引数,デフォルト引数,オブジェクトとしての関数 など
⑩ ライブラリの活用
問題解決のために適した代表的な標準ライブラリ又は外部ライブラリを利用し,プログラムを作成する。
修得項目 import 文,モジュール,パッケージ など
ざっと見た感じ、授業で習ったのがほとんどですな。見知らぬ単語も多少ありますが、これくらいの知識を要求されているくらいなら、私でもなんとかイケそうな気がする!いやイケるぞ!そう思い込んで、プログラミングの試験対策を講じることにしよう。
それでは本日も最後までお付き合いいただき、ありがとうございました!