本文へスキップ
BecomeCoder

Pythonコース · 第8章 Python の道具箱 ― もっと便利に、もっと実務らしく · レッスン33

可変長引数とアンパック ― 個数の決まらない引数を扱う

ブラウザで完結

導入

「いくつ渡されるか分からない引数」を受け取りたいことがあります。*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 の中でインデックス計算を手書きするより読みやすくなります。

やってみよう

totalprofile に渡す引数の数を変えたり、enumeratestart0 にしたりして、動きを確かめましょう。

演習

可変長引数を受け取る関数 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))

実際に動かしてみよう

下のエディタにPythonを書いて「実行」を押すと、ブラウザ内のPythonで出力が表示されます。本文の例をそのまま試したり、書き換えたりしてみましょう(input() を使う回は「標準入力」欄に値を入れてから実行します)。

Python — ブラウザ内で実行

ブラウザ内でPythonを動かす環境(Skulpt)を読み込みます(初回のみ少し時間がかかります)。
スクロールして表示された時点でも自動で読み込まれます。