Python3 コードがスッキリ!1行で複数の変数を初期化する方法!!

複数の変数の初期化時、複数行を使ってしまうと行数が増えコードが見づらくなってしまいます。
本記事では、1行で複数の変数を初期化してコードをスッキリさせる方法を紹介します。

a = 1
b = 2
c = 3
print(a, b, c)

シーケンスのアンパックを利用

シーケンスのアンパックを利用する方法です。
用途:複数の変数に異なる値を代入する。

a, b, c = 1, 2, 3 
print(a, b ,c)
"""
出力は下記です。
1 2 3
"""

タプル(1, 2, 3)はシーケンスなので、シーケンスのアンパックによりタプルの各要素が各変数に代入されています。
詳細は、「1行に複数要素(要素数固定):int型整数に代入」をご確認ください。

複数の変数への代入

複数の変数に代入する方法です。
a = b = c = 1の様な記述方法は、chainged assignmentと呼ばれている様です(*1)。
用途:複数の変数に同一の値を代入する。

a = b = c = 1
print(a, b ,c)
"""
出力は下記です。
1 1 1
"""

上記コードは、下記コードと同等です(*2)。

tmp = 1
a = tmp
b = tmp
c = tmp
del tmp
print(a, b ,c)
"""
出力は下記です。
1 1 1
"""

a= b = c = 1は代入文と呼ばれるものですが、代入の順番には注意が必要です。
a, b, cはターゲット(代入対象)であり、左のターゲットから順番に1が代入されます。

詳細は、下記をご確認ください。

代入文は式のリスト (これは単一の式でも、カンマで区切られた式リストでもよく、後者はタプルになることを思い出してください) を評価し、得られた単一の結果オブジェクトをターゲット (target) のリストに対して左から右へと代入してゆきます。

7. 単純文 (simple statement) — Python 3.9.4 ドキュメント

(*1):What is this kind of assignment in Python called? a = b = True – Stack Overflow Filip Roséen – refpの回答
(*2):python – Multiple-Target Assignments – Stack Overflow John Yの回答を参考にしました。

左のターゲットから順に代入されることの確認

l = [101, 102, 103]
a = 100
a = l[a] = 1
print(a)
print(l)
"""
1
[101, 1, 103]
"""
  • a = l[a] = 1では、先にa=1が処理されます。
  • その後、l[a] = 1が処理されます。上記によりaの値が100から1に変化したので、l[a] = 1の結果、l[1]に1が代入されます。これは、print(l)の出力にてl[1]の要素が1になっていることからわかります。
  • l[a]=1が先に処理された場合、l[100] = 1となりますが、l[100]ではなくl[1]が1となっています。このことからも、a = 1が先に処理されたことがわかります。

python – Multiple-Target Assignments – Stack OverflowのJohn Yの回答を参考にしました。

a= b = c = 1で左のターゲットから順に1が代入されることの確認

disモジュールで逆アセンブルし、処理の流れを確認します。

import dis
def myFunc():
    a = b = c = 1
dis.dis(myFunc)
"""
出力は下記です。
  3           0 LOAD_CONST               1 (1)
              2 DUP_TOP
              4 STORE_FAST               0 (a)
              6 DUP_TOP
              8 STORE_FAST               1 (b)
             10 STORE_FAST               2 (c)
             12 LOAD_CONST               0 (None)
             14 RETURN_VALUE
"""

・LOAD_CONSTによって、1をスタックに追加します。
・DUP_TOPによって、スタックの先頭にある参照を複製します。
・STORE_FASTによって、1(TOS スタックの先頭)を変数aに格納します。
・DUP_TOPとSTORE_FASTによって、1を複製し変数bに格納します。
・SOTRE_FASTによって、1を変数Cに格納します。

以上の処理手順から、a= b = c = 1は下記と同等ではないこともわかります(直感的には下記の様になりそうですが)。
c = 1
b = c
a = b

dis.dis()の出力結果の見方は下記が参考になります。

コメント

タイトルとURLをコピーしました