yiskw note

機械学習やプログラミングについて気まぐれで書きます

【Python】1行で複数の変数に同時に値を代入するのは遅い


概要

ネットでPythonの記事を読んでいると、以下のような1行で複数の変数に同時に値を代入する方法が速いという記事を見かけました。

a, b, c = 1, 2, 3

こちらについてちょっと怪しいなと思い、速度の比較、及び速度差の原因について調査してみました。
結論としては、1行で複数の変数に値を代入するのは遅いことがわかりました。(ただし、複数の変数に同じ値を代入する場合は、さほど遅くない)

以降調べた内容についてメモを残しています。
何か間違い等ございましたら、コメントにてご指摘いただけると幸いです。

複数の変数に同時に値を代入

ご存知の方も多いかと思いますが、Pythonでは複数の変数への値の代入を1行にまとめることができます。

a = 1
b = 2
c = 3

# 上と同じことをしている
a, b, c = 1, 2, 3

また複数の変数に同じ値を代入する場合は、以下のように書くこともできます。

a = 1
b = 1
c = 1

# 上と同じ
a = b = c = 1

詳しくは以下の記事をご参照ください。

Pythonで複数の変数に複数の値または同じ値を代入 | note.nkmk.me

ここからは以下の3つの方法について比較してきます。

  1. 複数行に分けて変数に値を代入する方法
  2. 1行で複数の変数に別々の値を代入する方法
  3. 1行で複数の変数に同じ値を代入する方法

実行環境

速度の比較

速度を比較した結果は以下です。
複数行に分けて変数を代入する方法が最も早く、1行で変数に値を代入する方法は遅いことが確認できました。
また1行で変数に値を代入する場合は、同じ値を代入する場合であれば、さほど遅くないことが確認できます。

速度差の原因

では、なぜ速度差が起きているのでしょうか?
原因を探るためにPythonの逆アセンブラであるdisを使用してみます。

import dis


def multiple_lines_assignment():
    a = 1
    b = 2
    c = 3
    

def single_line_assignment():
    a, b, c = 1, 2, 3
    

def single_line_same_value_assignment():
    a = b = c = 1


print("----- 複数行に分けて変数に値を代入する方法 -----\n")
dis.dis(multiple_lines_assignment)

print("\n----- 1行で複数の変数に別々の値を代入する方法 -----\n")
dis.dis(single_line_assignment)

print("\n----- 1行で複数の変数に同じ値を代入する方法 -----\n")
dis.dis(single_line_same_value_assignment)

結果

----- 複数行に分けて変数に値を代入する方法 -----

  5           0 LOAD_CONST               1 (1)
              2 STORE_FAST               0 (a)

  6           4 LOAD_CONST               2 (2)
              6 STORE_FAST               1 (b)

  7           8 LOAD_CONST               3 (3)
             10 STORE_FAST               2 (c)
             12 LOAD_CONST               0 (None)
             14 RETURN_VALUE

----- 1行で複数の変数に別々の値を代入する方法 -----

 11           0 LOAD_CONST               1 ((1, 2, 3))
              2 UNPACK_SEQUENCE          3
              4 STORE_FAST               0 (a)
              6 STORE_FAST               1 (b)
              8 STORE_FAST               2 (c)
             10 LOAD_CONST               0 (None)
             12 RETURN_VALUE

----- 1行で複数の変数に同じ値を代入する方法 -----

 15           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

これらを比較してみると、1行で複数の変数に別々の値を代入する方法では、 値がタプルとして読み込まれ、
その後アンパックによって各変数に値が割り振られている(UNPACK_SEQUENCE)ことがわかります。
そのため、複数行に分けて変数に値を代入する方法に比べて速度が遅くなっています。
1行で複数の変数に同じ値を代入する方法では、値のコピー(DUP_TOP)をしているため、アンパックほどではないものの、速度が遅くなっていると考えられます。

まとめ

1行で複数の変数に別々の値を代入する方法は、複数行に分けて変数に値を代入する方法より遅いことがわかりました。
またdisを使用して、原因がタプルをアンパックしているからであることも確認できました。

参考