ヘンなタイトルですんまそん。
チマチマとチビチビと Python の What’s New 翻訳続けてる。その中にこんなのがあった:
1 import timeit
2
3 timer1 = timeit.Timer('unicode("abc")')
4 timer2 = timeit.Timer('"abc" + u""')
5
6 # Run three trials
7 print(timer1.repeat(repeat=3, number=100000))
8 print(timer2.repeat(repeat=3, number=100000))
9
10 # On my laptop this outputs:
11 # [0.36831796169281006, 0.37441694736480713, 0.35304892063140869]
12 # [0.17574405670166016, 0.18193507194519043, 0.17565798759460449]
これは timeit モジュール初登場時(2.3)の timeit の例として挙げられていたもの。倍にもなるのか、と。
「特定の Python 実装に依存した最適化に拠るべからず」というのがスタイル標準の教え (PEP8 など) と思うし、これに関係したトピックもまさに見た記憶はあるけれど、実際これを自分の環境でも試してみて驚いてしまった。
Windows 7 の Python 2.7.9 (公式 CPython) でこんなことになった:
1 me@host: ~$ cat z.py
2 import timeit
3
4 timer0 = timeit.Timer('s = u"abc"')
5 timer1 = timeit.Timer('unicode("abc")')
6 timer2 = timeit.Timer('"abc" + u""')
7
8 # Run three trials
9 print(timer0.repeat(repeat=3, number=100000))
10 print(timer1.repeat(repeat=3, number=100000))
11 print(timer2.repeat(repeat=3, number=100000))
12 me@host: ~$ python z.py
13 [0.0018384687723313655, 0.001671685143299211, 0.0017058971697673452]
14 [0.02718402093091779, 0.025255317938776722, 0.025425095120124842]
15 [0.0025043203374674333, 0.0017563599088078335, 0.0017572152094695453]
16 me@host: ~$
なんで 10 倍の開きにもなるんだろう?
これを知ったからといって何か得するだろうか、というのは疑問。Python 3 系では通用しないし。けどここまで差があるのはなんでなんだろうか、というのは気にはなる。
個人的には unicode コンストラクタ(関数)をダイレクトに使うことがほとんどないので余計困りはしない。とりわけ Python 3 系で「も」動作するコードを書こうとすると、「移植性のために」unicode を明示的に使うのを避けるからさ。だから無意識に「速度で問題が出る」コードを避けていたことにはなる。けど「unicode 型にするために」という明確な意図を持って「空 unicode リテラルを足し算で」なんてコードを書く人、いるけ? おらんでしょう。
CPython 以外でどうなのかが気になるのと、あと、なんで What’s New ではこれをあえて例として選んだのかの著者の真意を知りたい。なんかしら有名なの?