10

したがって、リストを取得して 2 番目のリストのメンバーを最初のリストに追加するには、2 つの方法があります。リスト連結を使用するか、それを反復することができます。あなたはできる:

for obj in list2:
    list1.append(obj)

または次のことができます。

list1 = list1 + list2

また

list1 += list2

私の質問は次のとおりです。どちらが速いですか、なぜですか? 2 つの非常に大きなリスト (10000 オブジェクト以上) を使用してこれをテストしたところ、反復法はリストの連結 (l1 = l1 + l2 など) よりもはるかに高速であるように見えました。どうしてこれなの?誰か説明できますか?

4

3 に答える 3

15

appendは各項目を一度に 1 つずつ追加します。これが速度低下の原因であり、 への関数呼び出しが繰り返されるためappendです。

ただし、この場合、+=演算子はのシンタックス シュガーではありません+。演算子は実際に新しいリストを作成してから割り当て直すの+=ではなく、左側のオペランドをその場で変更します。timeit両方とも10,000回使用すると、それはかなり明白です。

>>> timeit.timeit(stmt="l = l + j", setup="l=[1,2,3,4]; j = [5,6,7,8]", number=10000)
0.5794978141784668
>>> timeit.timeit(stmt="l += j", setup="l=[1,2,3,4]; j = [5,6,7,8]", number=10000)
0.0013298988342285156

+=はるかに高速です(約500倍)

extend次のようなもので(別のリストだけでなく)イテラブルを追加できるリストのメソッドもありますl.extend(l2)

>>> timeit.timeit(stmt="l.extend(j)", setup="l=[1,2,3,4]; j = [5,6,7,8]", number=10000)
0.0016009807586669922
>>> timeit.timeit(stmt="for e in j: l.append(e)", setup="l=[1,2,3,4]; j = [5,6,7,8]", number=10000)
0.00805807113647461

論理的には追加と同等ですが、ご覧のとおりはるかに高速です。

これを説明するには、新しいリスト全体を作成する必要が+ あるため、反復はより高速です+

extend組み込みのリスト メソッドであり、最適化されているため、反復よりも高速です。繰り返し追加することと論理的に同等ですが、実装が異なります。

+=extendリストをその場で変更できるため、リストをどれだけ大きくする必要があるかがわかり、関数呼び出しを繰り返す必要がないため、より高速です。リストに別のリスト/タプルを追加していると想定しています

于 2013-07-05T00:08:42.337 に答える
0

次のコードを実行しました

l1 = list(range(0, 100000))
l2 = list(range(0, 100000))

def t1():
    starttime = time.monotonic()
    for item in l1:
        l2.append(item)
    print(time.monotonic() - starttime)

l1 = list(range(0, 100000))
l2 = list(range(0, 100000))

def t2():
    starttime = time.monotonic()
    global l1
    l1 += l2
    print(time.monotonic() - starttime)

これは、リスト (+=) を追加する方が高速であることを示しています。

0.016047026962041855

0.0019438499584794044

于 2013-07-05T00:08:14.853 に答える
0

測定が間違っています。appendここで Linux x64 上の cPython 2.7.5 で示されているように、(少なくとも cpython では) 多くの関数呼び出しのオーバーヘッドが実際のリスト操作に関係するすべてのものを小さくするため、複数回反復して呼び出すと、1 回の呼び出しを行うよりもはるかに遅くなります。 :

$ python -m timeit -s 'x = range(10000);y = range(10000)' 'for e in y:x.append(e)'
100 loops, best of 3: 2.56 msec per loop
$ python -m timeit -s 'x = range(10000);y = range(10000)' 'x = x + y'
100 loops, best of 3: 8.98 msec per loop
$ python -m timeit -s 'x = range(10000);y = range(10000)' 'x += y'
10000 loops, best of 3: 105 usec per loop
$ python -m timeit -s 'x = range(10000);y = range(10000)' 'x.extend(y)'
10000 loops, best of 3: 107 usec per loop

リストの 2 番目のコピーを作成することに注意してくださいx = x + y(少なくとも cPython では)。x.extend(y)とそのいとこは、実際に Python メソッドを呼び出すオーバーヘッドなしで、複数回x += y呼び出すのと同じことを行います。append

于 2013-07-05T00:10:17.410 に答える