こんにちはid:hirokikyです。
今回はPyQの学習サポートプランでよくいただく*args
、**kwargs
に関する質問です。
この機能は必ず知っていないといけないというものではありませんが、デコレーターを定義する際やクラスの継承をする際に必要となってきます。
ぜひ基本をここでシッカリと押さえておきましょう!
いただいた質問
可変長位置
*args
と可変長キーワード**kwargs
の役割がピンときません。
回答
まずPythonにおける *args
、 **kwargs
は、関数が引数をうけとる方法の1つだと覚えておきましょう。
たとえば def hello(name):
の name
は、hello関数の引数です。これと同じように *args
も引数に過ぎません。
まず *args
から理解しよう
まず *args
が何かについて理解しましょう。以下のhello関数は *args
を使った関数です。
hello関数には "hiroki", "saito"
という2つの位置引数を渡して呼び出しています。
def hello(*args): print(args) hello("hiroki", "saito") # ('hiroki', 'saito') と表示されます
実行すると ('hiroki', 'saito')
と表示されます。
これはhello関数内のargs引数に、呼び出し時に渡された2つの引数がタプルに入ってくるからです。
このように *args
は単純に引数を受け取る方法の1つに過ぎません。
このhello関数の代わりに、以下のような普通のhello関数を定義して、タプルを使って関数を呼び出しても結果は違いありません。
def hello(args): print(args) t = ("hiroki", "saito") # タプルを定義する hello(t) # ('hiroki', 'saito') と表示されます
つまり3行にまとめると以下のような仕組みです。
- def hello(*args):のように関数を定義する
- hello("hiroki", "tsutomu")のように引数を複数渡せる
- hello 関数内で args は、渡された引数のタプルになる
**kwargs
を理解しよう
**kwargs
も基本的には *args
と考え方は同じです。
hello関数を **kwargs
を使って書いてみましょう。
hello関数には name="hiroki", hometown="osaka"
という値を渡して呼び出します。
def hello(**kwargs): print(kwargs) hello(name="hiroki", hometown="osaka") # {'name': 'hiroki', 'hometown': 'osaka'} と表示されます
実行すると {'name': 'hiroki', 'hometown': 'osaka'}
と表示されます。
**kwargs
とした場合は、 name="hiroki"
のようにキーワード引数として渡した値が、 {"name": "hiroki"}
のような辞書として関数内で使えます。
基本的な考え方は *args
と **kwargs
は同じで、hello関数に任意の数の引数を渡せるようにするものです。
*args
は位置引数がタプルに、 **kwargs
はキーワード引数が辞書として渡されます。
名前は何でもOK
ここまで *args
、 **kwargs
と呼んできましたが、この引数名は自由です。
たとえば以下のhello関数では *names
という引数の名前にしています。
def hello(*names): print(names)
この場合は names
がタプルになります。
**kwargs
も同じで、 **options
や **profile
など任意の名前にできます。
ポイントは *
や **
を引数の前に書くことです。
何と呼べば良いもの?
*args
や **kwargs
というと何と呼べば良いのか少しややこしいですね。
それぞれ可変長位置引数、可変長キーワード引数と呼びます。「hello関数のargs
は可変長位置引数です」のように使うと良いでしょう。
簡単に、「argsは可変長引数です」と言っても伝わることは多いです。
用語集 - Python3ドキュメント https://docs.python.org/ja/3/glossary.html#term-parameter
どこで使われるもの?
一番わかりやすい例としては、 print
関数そのものです。
print
関数には任意の数の引数を渡せます。
これは print
関数が可変長引数として引数を受け取るからです。
print("私は", "hiroki", "という名前です", "!") # 「私は hiroki という名前です !」と表示されます
もし自分で関数を定義しようというときも、可変長引数は活用できます。
ですが多くの場合において、普通の関数を定義するのであれば普通の引数としてタプルや辞書を受け取るほうがわかりやすいと私は感じます
(書き方の好みのレベルになります)。
デコレーターを定義する場合や、クラスの継承をするときに可変長引数を受け取ることが多くなるでしょう。
たとえば以下の show_args
デコレーターは、どんな引数を受け取る関数に対しても使えるよう作られています。
これはデコレーターを理解していないと難しいかと思いますので、わからない場合は「なるほど、こう活用する場もあるのか」と知っていただければ十分です。
def show_args(f): """ 関数につけると、実行のたびに引数を表示するようにするデコレーター """ def _wrapped(*args, **kwargs): print(args) print(kwargs) return f(*args, **kwargs) return _wrapped @show_args def foobar(name, required=False): ...
まとめ
Pythonの *args
、 **kwargs
という可変長引数について説明しました。
PyQでもこれらについて学べるコンテンツがありますので、ぜひ併せてご活用ください。
可変長引数については以下で学べます。
デコレータについてはこちらで学べます
また、ビープラウド著書の「自走プログラマー」にも可変長引数について記載しています。下記のURLから可変長引数に関する部分を抜粋したページに飛べますのでご覧ください。