10

この癖に出くわしたとき、私はただいじっていました。そして、私は自分が狂っていないことを確認したかった.

次のコード (2.x および 3.x で動作):

from timeit import timeit
print ('gen: %s' % timeit('"-".join(str(n) for n in range(1000))', number=10000))
print ('list: %s' % timeit('"-".join([str(n) for n in range(1000)])', number=10000))

各バージョン、同じマシンで 3 回実行します。

注:ここではスペースを節約するために、タイミングを同じ行にグループ化しました。

私のPython 2.7.5では:

gen: 2.37875941643, 2.44095773486, 2.41718937347
list: 2.1132466183, 2.12248106441, 2.11737128131

私のPython 3.3.2では:

gen: 3.8801268438439718, 3.9939604983350185, 4.166233972077624
list: 2.976764740845537, 3.0062614747229555, 3.0734980312273894

これはなぜなのだろうか....文字列の実装方法と関係があるのでしょうか?


編集:range()これも2.xから3.xにわずかに変更されたため、使用せずにもう一度やりました。代わりに、以下の新しいコードを使用します:

from timeit import timeit
print ('gen: %s' % timeit('"-".join(str(n) for n in (1, 2, 3))', number=1000000))
print ('list: %s' % timeit('"-".join([str(n) for n in (1, 2, 3)])', number=1000000))

Python 2.7.5 のタイミング:

gen: 2.13911803683, 2.16418448199, 2.13403650485
list: 0.797961223325,  0.767758578433, 0.803272800119

Python 3.3.2 のタイミング:

gen: 2.8188347625218486, 2.882846655874985, 3.0317612259663718
list: 1.3590610502957934, 1.4878876089869366, 1.4978070529462615

EDIT2:計算を中断するものがいくつかあったようです。そのため、最小限に抑えてみました。

新しいコード:

from timeit import timeit
print ('gen: %s' % timeit('"".join(n for n in ("1", "2", "3"))', number=1000000))
print ('list: %s' % timeit('"".join([n for n in ("1", "2", "3")])', number=1000000))

タイミング Python 2.7.5:

gen: 1.47699698704, 1.46120314534, 1.48290697384
list: 0.323474182882, 0.301259632897, 0.323756694047

タイミング Python 3.3.2:

gen: 1.633002954259608, 1.6049987598860562, 1.6109927662465935
list: 0.5621341113519589, 0.5789849850819431, 0.5619928557696119

違いは明らかです。2.x では速く、3.x では遅くなります。その理由が気になります...

4

2 に答える 2

7

私はまだpython3.3に取り組んでいません。私が以下に述べたこれらはすべて、観察に基づいています。

Python 3.3 と Python 2.7.3 では、次のコードに Python 逆アセンブラーを使用しました。

s = """
''.join([n for n in ('1', '2', '3')])
"""

アップコードに変更があることがわかりました。

パイソン 2.7.3

Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> import dis
>>> from timeit import timeit
>>> s = """
... ''.join([n for n in ('1', '2', '3')])
... """
>>> timeit(s, number=100000)
0.08443676085287867
>>>
>>>
>>> c = compile(s, '<string>', 'exec')
>>> dis.dis(c)
  2           0 LOAD_CONST               0 ('')
              3 LOAD_ATTR                0 (join)
              6 BUILD_LIST               0
              9 LOAD_CONST               5 (('1', '2', '3'))
             12 GET_ITER
        >>   13 FOR_ITER                12 (to 28)
             16 STORE_NAME               1 (n)
             19 LOAD_NAME                1 (n)
             22 LIST_APPEND              2
             25 JUMP_ABSOLUTE           13
        >>   28 CALL_FUNCTION            1
             31 POP_TOP
             32 LOAD_CONST               4 (None)
             35 RETURN_VALUE
>>>

パイソン3.3

Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:55:48) [MSC v.1600 32 bit (In
tel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import dis
>>> from timeit import timeit
>>> s = """
... ''.join([n for n in ('1', '2', '3')])
... """
>>> timeit(s, number=100000)
0.13603410021487614
>>>
>>>
>>> c = compile(s, '<string>', 'exec')
>>> dis.dis(c)
  2           0 LOAD_CONST               0 ('')
              3 LOAD_ATTR                0 (join)
              6 LOAD_CONST               1 (<code object <listcomp> at 0x01F70BB
0, file "<string>", line 2>)
              9 LOAD_CONST               2 ('<listcomp>')
             12 MAKE_FUNCTION            0
             15 LOAD_CONST               7 (('1', '2', '3'))
             18 GET_ITER
             19 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             22 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             25 POP_TOP
             26 LOAD_CONST               6 (None)
             29 RETURN_VALUE
>>>

アップコードから、変更されたのはリスト内包表記であることがわかったので、両方のバージョンでリスト内包表記をチェックしました

パイソン 2.7.3

Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>>
>>>
>>> import dis
>>> from timeit import timeit
>>> s = """
... [i for i in ('1', '2', '3')]
... """
>>> timeit(s, number=100000)
0.059500395456104374
>>> c = compile(s, '<string>', 'exec')
>>> dis.dis(c)
  2           0 BUILD_LIST               0
              3 LOAD_CONST               4 (('1', '2', '3'))
              6 GET_ITER
        >>    7 FOR_ITER                12 (to 22)
             10 STORE_NAME               0 (i)
             13 LOAD_NAME                0 (i)
             16 LIST_APPEND              2
             19 JUMP_ABSOLUTE            7
        >>   22 POP_TOP
             23 LOAD_CONST               3 (None)
             26 RETURN_VALUE
>>>

パイソン3.3

Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:55:48) [MSC v.1600 32 bit (In
tel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>>
>>>
>>> import dis
>>> from timeit import timeit
>>> s = """
... [i for i in ('1', '2', '3')]
... """
>>> timeit(s, number=100000)
0.09876976988887567
>>> c = compile(s, '<string>', 'exec')
>>> dis.dis(c)
  2           0 LOAD_CONST               0 (<code object <listcomp> at 0x01FF0BB
0, file "<string>", line 2>)
              3 LOAD_CONST               1 ('<listcomp>')
              6 MAKE_FUNCTION            0
              9 LOAD_CONST               6 (('1', '2', '3'))
             12 GET_ITER
             13 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             16 POP_TOP
             17 LOAD_CONST               5 (None)
             20 RETURN_VALUE
>>>

私はpython3で作業したり、変更を確認したりしていません。リスト内包表記の実装が変更されたようです。python3.3 には MAKE_FUNCTION と CALL_FUNCTION があります。(現在、python2.7では関数への呼び出しはコストがかかります。python3.3で関数への呼び出しがまだコストがかかるかどうかはわかりません。その場合は、時間が追加される可能性があります。)

于 2013-06-13T09:22:01.817 に答える
1

リンゴとリンゴを比較しているわけではありません。

Python 2 では、Python 3 で (ほとんど)strと呼ばれるものです。bytes

Python 3 では、Python 2strで呼ばれるものですunicode

于 2013-06-06T22:51:50.553 に答える