ゼロからのPython入門講座タプルとコレクション コレクションのアンパック

タプルコレクションシーケンスコレクションのアンパック

変数 では、代入文を使って、変数に値を代入する方法を解説しました。

普通の代入文は、右辺の値を、左辺に指定した変数に代入します。

In [52]:
variable = 1000   # variableに 1000 を代入
print(variable)
1000

コレクションのアンパック

代入式の右辺がコレクションなどの場合には、左辺に複数の変数名を指定して、コレクションの要素を一括して変数に代入できます。

たとえば、右辺が [1, 2, 3] のように、要素が3つあるリストの場合、左辺に var1, var2, var3 と3つの変数名を指定できます。

In [56]:
list_obj = [1, 2, 3]
var1, var2, var3 = list_obj  # var1, var2, var3 に、list_objの要素を順に代入

print(var1, var2, var3)
1 2 3

このように記述すると、変数 var1var2var3 には、右辺のリストオブジェクトの要素が一つずつ順番に代入されます。この場合、var1 には list_obj の最初の要素である 1が、var2var3 には、それぞれ2番目と3番目になる 23 が代入されます。

このように、コレクションの要素を一括して変数に代入する方法を、アンパック(unpack) といいます。

右辺には、リストオブジェクト以外にタプルなどのコレクションも指定できます。

In [57]:
var1, var2, var3 = (1, 2, 3)  # タプルのアンパック
print(var1, var2, var3)
1 2 3

文字列を代入すると、1文字ずつ分割して代入されます。

In [60]:
var1, var2, var3 = "ABC" # 文字列のアンパック
print(var1, var2, var3)
A B C

アンパック代入を行う場合は、右辺のコレクションの要素数と、左辺に指定する変数の数が一致する必要があります。一致しない場合は、次のようなエラーになります。

In [61]:
var1, var2 = "ABC" # 文字列のアンパック
print(var1, var2)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-61-08fa34f2a626> in <module>
----> 1 var1, var2 = "ABC" # 文字列のアンパック
      2 print(var1, var2)

ValueError: too many values to unpack (expected 2)

この例では、長さが3の文字列を、var1var2 という2つの変数に代入しようとしていますが、文字が一つ余ってしまうためにエラーとなります。

アンパックの使用例

アンパックを利用した代入は、Pythonプログラミングで頻繁に利用されます。

タプルの書き方 では、例として、東京都にある人形町駅の緯度と経度を、次のようなタプルで記述しました。

ningyocho = (35.686321, 139.782211)

このタプルから、駅の緯度と経度を取り出し、出力してみましょう。

タプルから値を取り出すには、インデックスを指定して値を取り出す方法があります。この方法で処理を記述すると、こうなります。

In [65]:
ningyocho = (35.686321, 139.782211)  # (緯度, 経度) のタプル

ido = ningyocho[0]  # ningyocho から緯度を取り出す
keido = ningyocho[1] # ningyocho から経度を取り出す

print("人形町は緯度:", ido, "経度:", keido)
人形町は緯度: 35.686321 経度: 139.782211

この書き方でも間違いではないのですが、2行にわけてそれぞれ緯度と経度を取り出すのは、ちょっとまだるっこしい感じがしませんか?

このような場合、アンパックを使うと、

In [ ]:
ningyocho = (35.686321, 139.782211)  # (緯度, 経度) のタプル

ido, keido = ningyocho  # ningyocho から緯度と経度を取り出す

print("人形町は緯度:", ido, "経度:", keido)

のように、一行ですっきりと記述出ます。

関数とアンパック

また、アンパックは、複数の値を戻り値とする 関数 でよく使われます。

合計感染者数を for 文で求める では、次のような、伝染病の合計感染者数を求める処理を書きました。

cases = [100, 125, 110, 135, 93, 95, 93]

total = 0 # 合計感染者数の初期値 0 を設定
for cases_of_day in cases:
    total = total + cases_of_day

print("合計感染者数は:", total)

このプログラムで、ついでに毎日の感染者数の平均値も求めてみましょう。

平均値は

合計感染者数 ÷ データの日数

で求められます。

この場合、データの日数 は 変数 cases の要素の数ですから、len(cases) で求められます。ですから、平均値を求める処理を追加すると、次のようになります。

In [7]:
cases = [100, 125, 110, 135, 93, 95, 93]

total = 0 # 合計感染者数の初期値 0 を設定
for cases_of_day in cases:
    total = total + cases_of_day

# 合計感染者数 ÷ データの日数 で平均感染者数を求める
average = total / len(cases)

print("合計感染者数は:", total)
print("平均感染者数は:", average)
合計感染者数は: 751
平均感染者数は: 107.28571428571429

合計値と平均値を求める関数を作成する

この、合計値と平均値を求める処理を 関数 にして、病気の感染者だけでなく、数値のコレクションならどんなデータでも合計値と平均値を求められるようにしてみましょう。

この関数は、total_and_average() という名前にしましょう。引数 として リスト などを指定すると、戻り値 としてコレクションの要素の合計値と平均値を求めます。

関数 total_and_average() の定義は、次のようになります。

In [3]:
def total_and_average(values):
    total = 0 # 合計値の初期値 0 を設定
    for value in values:
        total = total + value

    # データの件数を求める
    num = len(values)
    
    # 合計値 ÷ 件数 で平均値を求める
    average = total / num

    # 戻り値として (合計値, 平均値) のタプルを返す
    return (total, average)

関数で計算した結果は、return文 を使って、戻り値として返します。

しかし、関数 total_and_average() は合計値と平均値の2つを計算しますが、 return文 に指定できる戻り値は一つだけです。

そこで、return文には (合計値, 平均値) のタプルを指定し、二つの値を一つのタプルにまとめて返り値とします。 このようにすれば、total_and_average() を利用するときには、タプルのアンパックを利用して

In [6]:
values = [100, 200, 20, 50, 90]
total, average = total_and_average(values)
print(values, "の", "合計は", total, "平均は", average, "です。")
[100, 200, 20, 50, 90] の 合計は 460 平均は 92.0 です

のように書けます。

もう一つの例として、total_and_average() を修正し、コレクションに含まれるデータの件数も戻り値として返すようにしてみましょう。この関数は total_and_average_and_number() という名前とし、返す値が二つから三つになります

In [7]:
def total_and_average_and_number(values):
    total = 0 # 合計値の初期値 0 を設定
    for value in values:
        total = total + value

    # データの件数を求める
    num = len(values)
    
    # 合計値 ÷ 件数 で平均値を求める
    average = total / num

    # 戻り値として (合計値, 平均値, 件数) のタプルを返す
    return (total, average, num)

total_and_average_and_number() を利用するときも、同じようにタプルのアンパックを利用して次のように書けます。

In [9]:
values = [100, 200, 20, 50, 90]
total, average, number = total_and_average_and_number(values)
print(values, "の", "合計は", total, "平均は", average, "件数は", number, "です。")
[100, 200, 20, 50, 90] の 合計は 460 平均は 92.0 件数は 5 です。

このように、戻り値としてタプルを使い、複数の値を一度に返す関数はとてもよく使われます。テクニックとして覚えておきましょう。

Copyright © 2001-2021 python.jp Privacy Policy python_japan
Amazon.co.jpアソシエイト
Amazonで他のPython書籍を検索