はじめに
Pythonを学ぶため、Pythonの基礎を本ページに記載します。
関数
関数の引数は、型がないので、注意が必要です。attack
関数の引数は、文字列なのです。
パラメーター(引数)が1つの場合
def add_sound(attack): for i in range(5): # 5回繰り返す print(attack, '-->パコーン') # パラメーターの値に擬音を付けて表示 return attack add_sound('スマッシュ')
パラメーター(引数)が複数の場合
def calculate_add(a, b): result_calculate = a + b return result_calculate result = calculate_add(3, 5) print(result)
デフォルトパラメーターも使えます
def calculate_add(a=1, b=2): result_calculate = a + b return result_calculate #result = calculate_add(3, 5) result = calculate_add() print(result)
可変長パラメーターも使えます
# パラメーター名の前にアスタリスク(*)を付けると可変長パラメーターとなります def sequence_sound(*args): for a in(args): print(a) print(args) sequence_sound('ポーン', 'パコーン', 'スコーン')
[実行イメージ]
ポーン パコーン スコーン ('ポーン', 'パコーン', 'スコーン')
キーと値がセットになったパラメーター
「** パラメーター名」と書くとそのパラメーターは辞書型になります。
# パラメーター名の前にアスタリスク(*)を付けると可変長パラメーターとなります def attacks(**kwargs): print(kwargs) attacks(volley='ポーン', smash='パコーン')
パラメーターで関数を取得して、これを実行する
# パラメーターで関数を取得し、これを実行する関数を定義 # 関数をパラメーターで取得したり、戻り値として返す関数を高階関数と呼ぶ def attack_sound(a, s): print(a, '-->', s) def run_something(func, arg1, arg2): func(arg1, arg2) run_something(attack_sound, 'ドロップショット', 'ポワーン') # ドロップショット --> ポワーン
関数内関数の定義
関数の中で関数を定義できます。複雑な処理を内部の関数に任せることで、コードの重複を避けることができます。
EX. 整数値の例
def outer(a, b): def inner(c, d): return c + d return inner(a, b) result = outer(1, 5) print(result) print(outer(1, 5))
関数内関数の定義2 (文字列を扱う場合)
関数のパラメーター名stroke
と関数内関数のパラメーター名s
が異なるようにします。
同一の場合は、コンパイラーによっては、警告を受けます。
def add_sound(stroke): # 関数内関数 def inner(s): return s + ' --> ' + 'ぱっこーん' return inner(stroke) # 関数内関数の結果を返す result = add_sound('フォアハンドストローク') print(result) # フォアハンドストローク --> ぱっこーん
クロージャー
クロージャーとは、引数をセットして、関数を呼び出すコードを作っておいて、それをあとで実行できるようにするもの 関数を呼び出すパターンがあらかじめわかっているなら、それを記録しておいて、必要なときに実行するといった使い方ができます 次は、先の関数内関数をクロージャーにしたものです。
def add_sound(stroke): # クロージャーを定義する前に、呼び出すとエラーになるため、注意 # inner() # クロージャー def inner(): return stroke + ' --> ' + 'ぱっこーん' print(inner()) return inner # 関数内関数の結果を返す result = add_sound('フォアハンドストローク') print(result()) # フォアハンドストローク --> ぱっこーん # フォアハンドストローク --> ぱっこーん
関数内関数とクロージャーは以下の点が異なります。 inner()にはパラメーターがなく、代わりに外側の関数のstrokeパラメーターを直接使う add_sound()は、inner()関数の処理結果を返すのではなく、関数名(関数オブジェクト)を返す。
inner()関数はadd_sound()に渡されたstrokeにアクセスすることができ、これを覚えておくことができます。 これがクロージャーの重要なポイントです。
一方、add_sound()関数は、戻り値として、inner()を関数オブジェクトとして、返します。 strokeに渡す値を引数にしてadd_sound()を実行すれば、storkeの値を保持したinner()関数のオブジェクトが返されます。 この関数オブジェクトがすなわちクロージャーです。
def add_sound(stroke): # クロージャーを定義する前に、呼び出すとエラーになるため、注意 # inner() # クロージャー def inner(): return stroke + ' --> ' + 'ぱっこーん' return inner # 関数内関数の結果を返す a = add_sound('フォアハンドストローク') b = add_sound('バックハンドストローク') print(a()) print(b()) # フォアハンドストローク --> ぱっこーん # バックハンドストローク --> ぱっこーん
クロージャーaとbは、自分たちが作られたときに使われていたstrokeの内容を覚えています。あとは、実行したいタイミングでクロージャーを呼び出す。
ラムダ式
高階関数を用いた実現例は以下のようになります。
# 高階関数 (パラメータ def edit_sounds(sounds, func): for sound in sounds: print(func(sound)) # パラメーターで取得した値の末尾に感嘆符を追加する関数 def impact(sound): return sound + '!!!' pattern = ['ポーン', 'ぱっこーん', 'ビシ'] edit_sounds(pattern, impact) # 実行イメージ # ポーン!!! # ぱっこーん!!! # ビシ!!!
次に上をラムダ式で表現します。 ラムダ式を用いることで、impact関数が必要無くなりました。 ラムダ式は、名前のない処理部だけの関数であるため、無名関数と呼ばれる。
# 高階関数 (パラメータ def edit_sounds(sounds, func): for sound in sounds: print(func(sound)) # パラメーターで取得した値の末尾に感嘆符を追加する関数 def impact(sound): return sound + '!!!' pattern = ['ポーン', 'ぱっこーん', 'ビシ'] edit_sounds(pattern, lambda sound: sound + '!!!') # 実行イメージ # ポーン!!! # ぱっこーん!!! # ビシ!!!
ジェネレーター
ジェネレーターとは、Pythonのシーケンスを作成するオブジェクトのこと。ジェネレーターオブジェクトでは、戻り値をreturnではなくyieldで返す関数で生成することができます。反復処理のrange()もジェネレーター関数。
ジェネレーターでは、反復処理のたびに、最後に呼び出されたときに、シーケンスのどこを指していたか覚えていて、次の値を返します。
一方、通常の関数は、以前の呼び出しについて何も覚えていません。
def generate(str): for a in str: yield '[' + a + ']' gen = generate('ぱっこーん!') print(next(gen)) print(next(gen)) print(next(gen)) print(next(gen)) print(next(gen)) print(next(gen)) # print(next(gen)) 文字列以上に処理を行うとするとエラーになるため、注意 # 実行イメージ # [ぱ] # [っ] # [こ] # [ー] # [ん] # [!]
イテレート(反復処理)が可能なので、forステートメントを使ったほうが簡単です。
def generate(str): for a in str: yield '[' + a + ']' gen = generate('ぱっこーん!') for s in gen: print(s) # 実行イメージ # [ぱ] # [っ] # [こ] # [ー] # [ん] # [!]