0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Python 3 インデクサとシークエンスのアンパック(アンパック代入)

Last updated at Posted at 2020-06-12

Python 3ではtuplelistの分割にインデクサとシークエンスのアンパック(アンパック代入)の2通りが使えます。後者は慣例的なアンダースコア_による変数の破棄(_の使い回し)やアスタリスク*によるイテラブルの残った要素のリストへの代入が可能です。

なお、ここではPython 3ドキュメントにあるタプルへのアンパック以外、リストへの変換もコード中で左辺の要素の一部が変数として利用できればアンパックとみなしています。

[a, b] = 0, 1
# 上式はタプルからリストへの変換だが、リストの要素bは変数として使える
print(b)  # 1
b = 2
print(b)  # 2
print((a, b))  # (0, 2)

前提条件

インデクサが使える型と使えない型

インデクサが使える型は__index__抽象メソッドを持つクラスであり、使えない型は__index__を持たない型です。前者にはtuplelistのようなインデックスが意味を持つ型があり、後者にはsetfrozensetのようにインデックスが意味を持たない型です。後者にインデクサを使うとTypeErrorエラーが発生します。

tuple1 = (0, 1, 2)
t0 = tuple1[0]
print(0)  # 0
t0, t1, t2 = tuple1
print((t0, t1, t2))  # (0, 1, 2)

set1 = {0, 1, 2}
# s0 = set1[0]  # TypeError 'set' object is not subscriptable
# print(s0)
s0, s1, s2 = set1
print((s0, s1, s2))  # (0, 1, 2)

__index__を持つ型はtyping.SupportsIndexとして定義されています。

シークエンスのアンパック(アンパック代入)が使える型と使えない型

シークエンスのアンパックが使える型はsequenceに該当する型です。これは__getitem__特殊メソッドと__len__特殊メソッドを持つ型であり、tuplelistset等の多くの型が該当します。

インデクサもシークエンスのアンパックも使える型と使えない型

インデクサもシークエンスのアンパックも使える型は__index____getitem____len__を持つ型です。tuplelistはこれに該当しますが、setfrozensetは該当しません。

tupleの分割

前後の()が省略できるため、等号の左辺(アンパック先)の場合は分割して代入するように書けます。

インデクサ
t = ("a", "b", "c")
a = t[0]
b = t[1]
c = t[2]
print((a, b, c))  # ('a', 'b', 'c')
tuple→tupleのアンパック
# tuple→tuple
a, b, c = "a", "b", "c"
print((a, b, c))  # ('a', 'b', 'c')

# tuple→tuple
a, b, c = ("a", "b", "c")
print((a, b, c))  # ('a', 'b', 'c')

# tuple→tuple
(a, b, c) = ("a", "b", "c")
print((a, b, c))  # ('a', 'b', 'c')

# 不要な変数の省略
(_, b, _) = ("a", "b", "c")
print((_, b, _))  # ('c', 'b', 'c')

# 残りをlistにまとめる
(a, *bc, _, e) = ("a", "b", "c", "d", "e")
print((a, bc, _, e))  # ('a', ['b', 'c'], 'd', 'e')
tuple→listのアンパック
# tuple→list
[a, b, c] = ("a", "b", "c")
print((a, b, c))  # ('a', 'b', 'c')

# 不要な変数の省略
[_, b, _] = ("a", "b", "c")
print((_, b, _))  # ('c', 'b', 'c')

# 残りをlistにまとめる
[a, *bc, _, e] = ("a", "b", "c", "d", "e")
print((a, bc, _, e))  # ('a', ['b', 'c'], 'd', 'e')

listの分割

基本的にtupleと同様に扱えます。ただし、前後の[]は省略できません。

インデクサ
t = ["a", "b", "c"]
a = t[0]
b = t[1]
c = t[2]
print((a, b, c))  # ('a', 'b', 'c')
list→tupleのアンパック
# list→tuple
a, b, c = ["a", "b", "c"]
print((a, b, c))  # ('a', 'b', 'c')

# list→tuple
(a, b, c) = ["a", "b", "c"]
print((a, b, c))  # ('a', 'b', 'c')

# 不要な変数の省略
(_, b, _) = ["a", "b", "c"]
print((_, b, _))  # ('c', 'b', 'c')

# 残りをlistにまとめる
(a, *bc, _, e) = ["a", "b", "c", "d", "e"]
print((a, bc, _, e))  # ('a', ['b', 'c'], 'd', 'e')
list→listのアンパック
# list→list
[a, b, c] = ["a", "b", "c"]
print((a, b, c))  # ('a', 'b', 'c')

# 不要な変数の省略
[_, b, _] = ["a", "b", "c"]
print((_, b, _))  # ('c', 'b', 'c')

# 残りをlistにまとめる
[a, *bc, _, e] = ["a", "b", "c", "d", "e"]
print((a, bc, _, e))  # ('a', ['b', 'c'], 'd', 'e')

setの分割

インデクサは非対応です。タプルやリストにアンパックする場合、順序は保証されません。

setのアンパック
# set→tuple
# 順序は保証されない。
a, b, c = {"a", "b", "c"}
print((a, b, c))  # ('a', 'b', 'c')の並び替えのどれか

# set→list
# 順序は保証されない。
[a, b, c] = {"a", "b", "c"}
print((a, b, c))  # ('a', 'b', 'c')の並び替えのどれか

# set→set(できない)
# {a, b, c} = {"a", "b", "c"}
# print((a, b, c))  # ('a', 'c', 'b')

0
2
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?