導入
「いくつ渡されるか分からない引数」を受け取りたいことがあります。*args / **kwargs を使うと、個数が決まっていない引数をまとめて受け取れます。合わせて、リストや辞書を関数呼び出しに展開する書き方、そしてよく使う enumerate / zip も見ていきます。
説明
引数の前に * を付けると、渡された位置引数がいくつあってもタプルとして受け取れます。** を付けると、キーワード引数を辞書として受け取れます。
def total(*prices):
return sum(prices)
def profile(**info):
for k, v in info.items():
print(f"{k}: {v}")
print(total(100, 200, 300))
profile(name="太郎", age=25)
*prices には (100, 200, 300) というタプルが、**info には {"name": "太郎", "age": 25} という辞書が入ります。呼び出す側は普通に引数を並べるだけで、受け取る側の関数は「何個来ても対応できる」形になります。
逆に、すでにあるリストや辞書を関数呼び出しの引数に展開することもできます。呼び出す側で * / ** を使います。
nums = [100, 200, 300]
print(total(*nums)) # total(100, 200, 300) と同じ
data = {"name": "太郎", "age": 25}
def greet(name, age):
print(f"{name}さん({age}歳)")
greet(**data) # greet(name="太郎", age=25) と同じ
*nums は「リストの中身を、順番にバラして渡す」、**data は「辞書の中身を、キーワード引数としてバラして渡す」という意味です。関数を定義するときの *args / **kwargs(まとめる)と、呼び出すときの *リスト / **辞書(バラす)は、記号は同じでも向きが逆であることに注意してください。
添え字とペアで回したいときは enumerate、複数のリストを同時に回したいときは zip が定番です。
fruits = ["りんご", "みかん", "ぶどう"]
for i, fruit in enumerate(fruits, start=1):
print(f"{i}: {fruit}")
names = ["太郎", "花子"]
scores = [80, 95]
for name, score in zip(names, scores):
print(f"{name}: {score}点")
enumerate(fruits, start=1) は「1から始まる連番」と要素をペアで返します。zip(names, scores) は複数のリストから同じ位置の要素を順にペアにして返します。どちらも for の中でインデックス計算を手書きするより読みやすくなります。
やってみよう
total や profile に渡す引数の数を変えたり、enumerate の start を 0 にしたりして、動きを確かめましょう。
演習
可変長引数を受け取る関数 total(*prices) を定義し、渡された数値の合計を返すようにしてください。nums = [100, 200, 300] を *nums で展開して total(*nums) を呼び出し、結果を表示してください(結果は 600)。
ヒント1を見る
def total(*prices): return sum(prices)。
ヒント2を見る
nums = [100, 200, 300] のあと print(total(*nums))。