def main():
for i in xrange(10**8):
pass
main()
この Python コードは、(注: タイミングは Linux の BASH の time 関数を使用して行われます。) で実行されます。
real 0m1.841s
user 0m1.828s
sys 0m0.012s
ただし、forループが関数内に配置されていない場合は、
for i in xrange(10**8):
pass
その後、実行時間がずっと長くなります。
real 0m4.543s
user 0m4.524s
sys 0m0.012s
どうしてこれなの?
ベストアンサー1
関数内のバイトコードは次のようになります。
2 0 SETUP_LOOP 20 (to 23)
3 LOAD_GLOBAL 0 (xrange)
6 LOAD_CONST 3 (100000000)
9 CALL_FUNCTION 1
12 GET_ITER
>> 13 FOR_ITER 6 (to 22)
16 STORE_FAST 0 (i)
3 19 JUMP_ABSOLUTE 13
>> 22 POP_BLOCK
>> 23 LOAD_CONST 0 (None)
26 RETURN_VALUE
最上位レベルのバイトコードは次のようになります。
1 0 SETUP_LOOP 20 (to 23)
3 LOAD_NAME 0 (xrange)
6 LOAD_CONST 3 (100000000)
9 CALL_FUNCTION 1
12 GET_ITER
>> 13 FOR_ITER 6 (to 22)
16 STORE_NAME 1 (i)
2 19 JUMP_ABSOLUTE 13
>> 22 POP_BLOCK
>> 23 LOAD_CONST 2 (None)
26 RETURN_VALUE
違いはSTORE_FAST
より速い(!)STORE_NAME
これは、関数内ではi
がローカルですが、トップレベルではグローバルであるためです。
バイトコードを調べるには、dis
モジュール関数を直接逆アセンブルすることはできましたが、トップレベルのコードを逆アセンブルするには、compile
組み込み。