Python♪関数で複数の値を返すタプルの便利な機能

「タプルはあまり使いどころがない?」と思っていませんか?でも、タプルを使うと複数の値を一度に渡すことができます。特に関数の返り値(return)での使用は必須レベル。「ゼロから作るDeep Learning」でも多用していたので記事にしました。

なお、タプルには「*」を使うアンパックの機能もありますが、この記事では説明しません。

0.「ゼロから作るDeep Learning」のポイント整理シリーズ

この記事は「ゼロから作るDeep Learning」のポイント整理シリーズの記事です。シリーズの名前のとおり私の自習用のメモです。書籍では説明されない基礎文法や補足・関連事項などを説明しており、書籍がなくてもわかる内容になっています。

1.タプルのアンパックの使用例

以下、「ゼロからつくるDeep Learning」3.6.3 バッチ処理のサンプルコードから引用した1行です。タプルのアンパックをつかったPythonらしい表記方法なのですが、xの後に「,」がありますし、「_ =」ってなに?と思ってしまうかもしれません。

#コード01
x, _ = get_data()

2.タプルは外側の括弧を省略できる

それでは、順番に説明したいと思います。

タプルの代入では、普通に代入するとコード02の2行目のような書式になりますが、タプルの代入では一番外側の括弧は省略でき、5行目のような表記が可能です。結果も同じ出力になっています。

#コード02
a = (1, 2)
print(a)
print(a[0], a[1])
b = 1, 2
print(a)
print(a[0], a[1])
#出力02
(1, 2)
1 2
(1, 2)
1 2

3.タプルのアンパック

次にアンパックの機能を使ってみます。コード03の2~4行目では、タプル(1, 2)である変数aの要素をそれぞれ変数x, yに代入しています。

一方、7行目はタプルのアンパックを使った表記です。

更に、アンパックの左辺の括弧を省略できるので10行目のように記述できます。

#コード03
a = 1, 2
x = a[0]
y = a[1]
print(x, y)

(x, y) = a
print(x, y)

x, y = a
print(x, y)
#出力03
1 2
1 2
1 2

さらに、括弧の省略とタプルのアンパックを同時に使うとコード4の2行目のような記述が可能です。また、4行目のような記述も可能であり、数学の座標を記述する場合と似ているため直感的にわかりやすいのではないでしょうか。

#コード04
x, y = 1, 2
print(x, y)
(x, y) = (1, 2)
print(x, y)
#出力04
1 2
1 2

普通ならコード05のようにしなければならないところをアンパックを使うと1行で表記できます。

#コード05
x = 1
y = 2
print(x, y)

4.リストのアンパックも同じ

実はリストもアンパックが可能です。また、6行目のような表記もできます。

#コード06
x, y = [1, 2]
print(x, y)
(x, y) = [1, 2]
print(x, y)
[x, y] = [1, 2]
print(x, y)

4.入れ子のタプル

入れ子のタプルでも、アンパックの機能を使うことができます。

#コード07
a = (1, 2, (3, 4))

x, y, (z1, z2) = a
print(x, y, z1, z2)

x, y, z = a
print(x, y, z)
#出力07
1 2 3 4
1 2 (3, 4)

5.慣例的に使う「_」

コード08の4行目において、アンパックした要素x, y, zの中で実際に使用する変数がx, zだけだとします。そんな場合は、アンパックする時点でyは使用しないことを明示した方が読みやすいコードになります。

7行目では「y」の代わりに「_」を使い、2番目の要素は使わないことを明示しました。「_」は文法的に意味のある記号ではなく、変数名に「_」を用いただけです。出力08のを見ると変数「_」に2が代入されていることがわかります。

#コード08
a = (1, 2, 3)

x, y, z = a
print(x, y, z)

x, _, z = a
print(x, _, z)
#出力08
1 2 3
1 2 3

このように、アンパックしても使わない要素は慣例的に「_」という名前の変数にしますが、この慣例を知らないとびっくりしてしまいます。

6.関数で複数の値を返す

タプルのアンパックが最も必要とされるのは、関数で複数の値を返したいときではないでしょうか。

データの流れがわかりやすいプログラムを記述するためには、関数の入力や出力を明快にする必要があります。したがって、本来はgrobal変数は用いず、返り値を1つにするのが最もシンプルであり理想です。

しかし、実際のプログラミングでは複数の値を返したいケースも多く、タプルのアンパックは非常に便利です。

コード09は平均点算出プログラムです。5行目では( )が省略されていますが、(len(x), sum(x), mean)という3つの要素をもつタプルがreturnされています。

そして、8行目や12行目では返り値であるタプルがアンパックされているのです。

なお、12行目では必要ないため2つめの変数の変数名を「_」とし、使わない変数であることを明示しています。

また、16行目のように2カ所「_」を使ってもエラーにはなりません。その場合、変数「_」には、後ろ側のデータのsum(x)が代入されます。

#コード09
def calc_list(x):
    '''平均点算出プログラム'''
    mean = sum(x) / len(x)  #平均点
    return len(x), sum(x), mean

x = [7, 6 ,1 ,4, 2]
a1, a2, a3 = calc_list(x)
print(a1, a2, a3)

x = [100, 75 ,30 ,92, 46]
num, _, mean = calc_list(x)
print('受験者数は',num,'人。平均は',mean,'点')

x = [100, 75 ,30 ,92, 46]
_, _, mean = calc_list(x)
print('平均は',mean,'点')
print('変数_ =', _)

7.もう一度最初のコードを見てみよう

それでは、もう一度最初のコード01を見てみましょう。以下の関数get_data()の具体的なコードは、「3.6.2 ニューラルネットワークの推論処理」に記述されていますが、x_test, t_testという2つのデータをreturnで返しています。

コード01では、返り値として返されたタプル(x_test, t_test)をアンパックし、そのうちx_testを変数xに代入しています。もちろん、2つめのt_testは使わないことを明示するために変数名を「_」としました。変数「_」にはt_testのデータが代入されています。

#コード01
x, _ = get_data()

いかがでしょうか。タプルのアンパックは覚えておくべき機能のひとつですので、これを機会に知識を整理してみてください。

私が実際に購入した教材のご紹介

以下、私が実際に購入したPythonの教材をまとめてみました。 Pythonを学習する上で、少しでもお役に立つことができればうれしいです。

Python♪私が購入したPythonの書籍のレビュー
UdemyのPythonの動画講座を書籍を買う感覚で購入してみた

その他

Twitterへのリンクです。SNSもはじめました♪

以下、私が光回線を導入した時の記事一覧です。
 (1) 2020年「光回線は値段で選ぶ」では後悔する ←宅内工事の状況も説明しています。
 (2) NURO光の開通までWiFiルーターを格安レンタルできる
 (3) NURO光の屋外工事の状況をご紹介。その日に開通!
 (4) 光回線開通!実測するとNURO光はやっぱり速かった
 (5) ネット上のNURO光紹介特典は個人情報がもれないの?