■ はじめに
https://dk521123.hatenablog.com/entry/2019/09/22/000000
の続き。 関数の記事が長くなったので、整理して分冊。 また、Pythonの資格の問題ででてきた デフォルト引数の注意点などを記録。
目次
【0】関数の実体について 【1】デフォルト引数 1)デフォルト引数の使用上の注意 【2】 可変長引数 1)*args (タプル) ... 可変長引数 2)**kwargs (辞書) ... 名前付き可変長引数 3)補足:引数のアンパック(展開) 【3】 キーワード引数 1)キーワード引数 2)キーワード引数を強制する* 【4】関数の空実装 【5】内部関数(Inner Function)
【0】関数の実体について
* 関数の正体は、オブジェクトである * 関数を変数に格納して呼び出すことが可能
サンプル
def sample_method(name): print("Hello " + name) func = sample_method func("Mike") # Hello Mike
【1】デフォルト引数
* 「引数 = 初期値」にする
サンプル
def sayHello(name="Mike"): print("Hello, {}!".format(name)) sayHello()
出力結果
Hello, Mike!
1)デフォルト引数の使用上の注意
* リストや辞書などのオブジェクトをデフォルト指定した場合、 そのオブジェクトは関数定義時に生成され、 2回目以降に呼び出されたら、同じオブジェクトが使われる。
サンプル
def culc(a, b=1, list1=[], list2=[]): print(list1) print(list2) list1.append(a ** 2) list2.append(b ** 3) return list1, list2 print("Start") print(culc(1)) print("*******") print(culc(2, 3)) print("*******") print(culc(3, 4)) print("*******") print(culc(4, 5)) print("Done")
出力結果
Start [] [] ([1], [1]) ******* [1] << デフォルト値に前回の値が含まれている [1] << デフォルト値に前回の値が含まれている ([1, 4], [1, 27]) ******* [1, 4] << デフォルト値に前回の値が含まれている [1, 27] << デフォルト値に前回の値が含まれている ([1, 4, 9], [1, 27, 64]) ******* [1, 4, 9] << デフォルト値に前回の値が含まれている [1, 27, 64] << デフォルト値に前回の値が含まれている ([1, 4, 9, 16], [1, 27, 64, 125]) Done
【2】可変長引数
可変長引数には、以下の2種類ある。 1)*args ... 複数の引数をタプルとして受け取る(可変長引数) 2)**kwargs ... 複数の引数を辞書として受け取る(名前付き可変長引数)
1)*args (タプル) ... 可変長引数
* 「*【引数名】」にする
サンプル
# coding: UTF-8 def say_hello(*names): for name in names: print("Hello, {}!".format(name)) say_hello("Mike", "Tom", "Sam")
出力結果
Hello, Mike! Hello, Tom! Hello, Sam!
2)**kwargs (辞書) ... 名前付き可変長引数
* 「**【引数名】」にする
サンプル
def function(**key_values): for key, value in key_values.items(): print("Key = {}, Value = {}.".format(key, value)) def main(): function(A1='Mike', A2='Tom') if __name__ == '__main__': main()
出力結果
Key = A1, Value = Mike. Key = A2, Value = Tom.
3)補足:引数のアンパック(展開)
* アンパック (unpack) ... リストなどの要素を1つ1つ取り出し(展開)、関数に渡す操作
サンプル
list = ["A", "B", "C"] print(list) # ['A', 'B', 'C'] print(list[0], list[1], list[2]) # A B C print(*list) # A B C print(*list, sep=" => ") # A => B => C
参考文献
https://python.keicode.com/lang/list-unpack-asterisk.php
【3】キーワード引数
1)キーワード引数
* 引数を明示的に指定可能
サンプル
def say_hello(greeting="Hello", name="Smith"): print("{}, {}!".format(greeting, name)) say_hello() say_hello(name="Mike") say_hello(greeting="Good morning", name="Tom") say_hello(name="Sam", greeting="Good afternoon")
出力結果
Hello, Smith! Hello, Mike! Good morning, Tom! Good afternoon, Sam!
2)キーワード引数を強制する*
* 以下「(value1, value2, *, arg1=1.0, arg2=0.0):」のように アスタリスクを指定すると、アスタリスク以降の引数を指定する場合 メソッドの使用者側にキーワード引数を強制的に指定させる
https://yohhoy.hatenadiary.jp/entry/20150315/p1
サンプル (NGケース)
def sample_method(value1, value2, *, arg1=1.0, arg2=0.0): print("{} {} {} {}".format(value1, value2, arg1, arg2)) sample_method(1, 2) # ここはOK sample_method(1, 2, 1) # NG
出力結果
1 2 1.0 0.0 Traceback (most recent call last): File "c:/work/hello/hello.py", line 5, in <module> sample_method(1, 2, 1) TypeError: sample_method() takes 2 positional arguments but 3 were given
サンプル (OKケース)
def sample_method(value1, value2, *, arg1=1.0, arg2=0.0): print("{} {} {} {}".format(value1, value2, arg1, arg2)) sample_method(1, 2) # ここはOK sample_method(1, 2, arg1=1000) # OK
出力結果
1 2 1.0 0.0 1 2 1000 0.0
【4】関数の空実装
* pass を使う
サンプル
# coding: UTF-8 def sayHello2(): pass sayHello2()
出力結果
* 実行しても何も起こらない
【5】内部関数(Inner Function)
* 関数内で関数を定義できる * nonlocal については、以下の関連記事を参照のこと。
https://dk521123.hatenablog.com/entry/2019/12/12/232749
* 以下のハノイの塔に関する動画でも用いられている
https://www.youtube.com/watch?v=MLronWYaHw8
サンプル
def outer(): print("外部関数") def inner(): print("内部関数") # 外部関数から内部関数を呼び出す inner() outer()
出力結果
外部関数 内部関数
関連記事
Python ~ 基本編 / 関数 ~
https://dk521123.hatenablog.com/entry/2019/09/22/000000
Python ~ 基本編 / 文字列 ~
https://dk521123.hatenablog.com/entry/2019/10/12/075251
Python ~ 基本編 / global・nonlocal ~
https://dk521123.hatenablog.com/entry/2019/12/12/232749
Python ~ 基本編 / yield ~
https://dk521123.hatenablog.com/entry/2021/03/18/000000