読者です 読者をやめる 読者になる 読者になる

いろいろ備忘録日記

主に .NET と Python絡みのメモを公開しています。

Pythonメモ-06 (PEP-3132 Extended Iterable Unpacking)

概要

小ネタ。Python 3.0で追加された仕様です。

知ってるとちょっと楽できます。

以下のPEPです。

www.python.org

名前は、Extended Iterable Unpacking って感じのちょっとむずかしそうな

名前ですが、実際にコード見てみるとすぐ意味が分かります。

list01 = list(range(5))
first, *rest = list01

上記を実行すると

first=0
rest=[1, 2, 3, 4]

となります。つまり、「*」を付けた変数に残りがアンパックされます。

以前は、こう書いてました。

list01 = list(range(5))
first, rest = list01[0], list01[1:]

アンパックする部分は、左辺の末尾にないといけないわけではなく

str01 = 'hello world'
first, *rest, last = str01

のように記述することもできます。

この場合、ちゃんと first, last にも先頭と末尾の値が入ります。

サンプル

        # -----------------------------------------------
        # PEP 3132 Extended Iterable Unpacking は
        # Python 3.0 から追加された機能。
        #
        # 「*」を付けた変数に残りの値がアンパックされる
        # -----------------------------------------------
        # 以下のように iterable を右辺において
        # 左辺に複数の変数で受ける記述は昔からあったが
        # そこに、「*」を付与した変数を置くと
        # ここでアンパックされる。また、後ろに
        # アンパックではない通常の変数を置いても
        # 適切に解釈して値を設定してくれる。
        # -----------------------------------------------
        str01 = 'hello world'
        first, *rest, last = str01

        pr('first', first)
        pr('rest', rest)
        pr('last', last)

        # なので、シーケンスの先頭とそれ以外を分ける場合に
        seq01 = list(range(10))
        first, rest = seq01[0], seq01[1:]

        pr('first', first)
        pr('rest', rest)

        # とする必要がなく、以下のように書ける
        first, *rest = seq01

        pr('first', first)
        pr('rest', rest)

        # 同じことが for ステートメントでも適用できて以下のように書ける
        it01 = [tuple('hello'), tuple('world')]
        for _, *x, _ in it01:
            print(x)

        # 一つしか要素がない iterable の場合もちゃんと動く
        oneitem = [1]
        first, *rest = oneitem

        pr('first', first)
        pr('rest', rest)

        # さすがに要素がゼロの場合はエラーになる
        try:
            noitem = []
            first, *rest = noitem

            pr('first', first)
            pr('rest', rest)
        except ValueError as e:
            pr('noitem', e)

実行すると以下のようになります。

first='h'
rest=['e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l']
last='d'
first=0
rest=[1, 2, 3, 4, 5, 6, 7, 8, 9]
first=0
rest=[1, 2, 3, 4, 5, 6, 7, 8, 9]
['e', 'l', 'l']
['o', 'r', 'l']
first=1
rest=[]
noitem=ValueError('not enough values to unpack (expected at least 1, got 0)',)

ソースは、以下でも見れます。

github.com


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。