LoginSignup
31
15

More than 5 years have passed since last update.

[小ネタ] Pythonでは、 i+=1 よりも i = i+1の方が微妙に早い、というお話

Posted at

タイトル通りです。
もともと重い処理じゃないので、多分、これを知ったところで遅いプログラムがどうこうなるわけじゃないと思いますが、意外だったので小ネタとして。

コード
from __future__ import print_function
import timeit

print("i+=1\t", timeit.timeit("while i<1000000: i+=1", setup="i=0"))
print("i=i+1\t", timeit.timeit("while i<1000000: i=i+1", setup="i=0"))

print("a[0]+=1\t", timeit.timeit("while a[0]<1000000: a[0]+=1", setup="a=[0]"))
print("a[0]=a[0]+1\t", timeit.timeit("while a[0]<1000000: a[0]=a[0]+1", setup="a=[0]"))
Python2.7.8実行結果
i+=1     0.0610518455505
i=i+1    0.0599188804626
a[0]+=1  0.108623981476
a[0]=a[0]+1      0.108937978745
Python3.4.1実行結果
i+=1     0.08549419100017985
i=i+1    0.07950809699832462
a[0]+=1  0.14678418899711687
a[0]=a[0]+1      0.1382706459990004

Python3の方が遅いのね。知らなかった。
それはともかく。ごくわずかとはいえ、i+=1よりもi=i+1の方が早いことが分かる。

詳しく調べたわけではないが、原因はおそらく、こうだ。
i+=1の形式で代入の足し算を行うと、Pythonインタプリタは、まずi.__iadd__を探そうとする。そして、それがなかった場合にi.__add__を探す。
i=i+1の形式の足し算だと、Pythonインタプリタは初めからi.__add__を探す。
で、Python2, Python3とも、int.__iadd__は無いわけだ。
そのため、int.__iadd__を探して失敗する分だけ、i+=1の処理には無駄がある。
だからi=i+1形式の方が早いのだろう。

とはいえ、配列参照を2回しなければならないa[0]=a[0]+1よりは、a[0]+=1の方が早いだろう、と思ったのだが。
よくよく考えてみれば、メソッドの検索をするよりは、配列の0番目を余計に参照する方が早そうだ。

31
15
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
31
15