まとめへのリンク
はじめに
Pythonのコードをよく見ていると
def f(*args, **kwargs):
pass
*印付きのargs
そして**印付きのkwargs
というのを見かけます。
これは何なのでしょうか??
そもそも何の略?
args, kwargsはそれぞれ何の略なのでしょうか?
英語で引数をargument
といい、複数なら当然argumentsです。
Pythonはかなり省略しがちな記法であり
- args = argumentsの略 可変長タプル
- kwargs = keyword argumentsの略 キーワード辞書
という意味になっています。
*args
*args
は、関数で渡された余ったキーワード指定なし引数を、一個のタプルで受け取ることの出来る記法です。
例えば、以下のようにたくさん与えられた整数を足して返す関数accumulateを考えてみます。
def accumulate(*args):
print(args)
return sum(args)
'''
(10, 20, 30, 40)
100
'''
print(accumulate(10, 20, 30, 40))
accumulateに与えられた引数が多いため、*args
にタプルとして格納されます。
このように*args
のように、「アスタリスク」を一つ付けた引数を用意することで、余ったキーワード指定なし引数を一個に受け取ることができます。
さらに、タプルやリストのイテラブルは、「アスタリスク」を再びつけることで、アンパックすることができます。
def accumulate(*args):
print(*args)
return sum(args)
'''
10 20 30 40
100
'''
print(accumulate(10, 20, 30, 40))
よって、このアンパックを使うことで、何度でも他の関数にわたすことができます。
def accumulate(*args):
return sum(args)
def some_calc(*args):
# アンパックしてaccmulateにわたす
return accumulate(*args)
print(some_calc(10, 20, 30, 40))
**args
**args
は、キーワード指定引数で、他の引数で当てはまらなかったものを一緒くたに辞書として受け取ります。
def f(x, y, **kwargs):
print(x)
print(y)
print(kwargs)
'''
10
20
{'a': 20, 'b': 'hello'}
'''
f(x=10, y=20, a=20, b="hello")
上記では、x, yはすでに関数fの引数に存在するためそっちに流れますが、何も受け取り手がないa, bは残念ながらkwargsに一緒くたにされてしまいます。
辞書もアンパックが可能です。
「アスタリスク」を一つのみ使うと、キーのみ取り出せます。
そして、2つ使うと、a=20, b="hello"のような形になります。
def f(x, y, **kwargs):
print(x)
print(y)
print(*kwargs)
#print(**kwargs)
'''
10
20
a b
'''
f(x=10, y=20, a=20, b="hello")
print(**kwargs)
は残念ながらうまく動きません。エラーが出てしまいます。
Pythonのprintに
print(a=20, b="hello")
という記法が用意されていないためです。
最後に
*args
, **kwargs
は、動的な言語だからこそできる記法であり、
これがよくPythonのパッケージのdef __init__などで使用されています。
これによって、ユーザから与えられたパラメータなどを辞書やタプルで受け取ることができ、多くの挙動を許容してくれます。
varsと一緒に活用すると、非常に便利な挙動を実行することができます。
それは別の記事で扱いたいと思います。