What is the preferred way to compose a set from multiple lists in Python'u yanıtlamaya çalışırken, bazı performans analizleri yaptım ve biraz şaşırtıcı bir sonuçla karşılaştım.Birleştirilmiş bir listeden bir grup neden `.update` kullanmadan daha hızlı oluşturuluyor?
kurulum için
python -m timeit -s '
import itertools
import random
n=1000000
random.seed(0)
A = [random.randrange(1<<30) for _ in xrange(n)]
B = [random.randrange(1<<30) for _ in xrange(n)]
C = [random.randrange(1<<30) for _ in xrange(n)]'
kullanarak, aşağıdaki parçacıkları zaman aşımına: Benim için sürpriz
> $TIMEIT 'set(A+B+C)'
10 loops, best of 3: 872 msec per loop
> $TIMEIT 's = set(A); s.update(B); s.update(C)'
10 loops, best of 3: 930 msec per loop
> $TIMEIT 's = set(itertools.chain(A,B,C))'
10 loops, best of 3: 941 msec per loop
, set(A+B+C)
o 3000000 unsurları içeren bir ara liste oluşturur olmasına rağmen en hızlı olduğunu . .update
ve itertools.chain
öğelerinin ikisi de daha yavaştır;
Neler oluyor burda?
DÜZENLEME: İkinci makinede (OS X 10.10.5, Python 2.7.10, 2,5 GHz Core i7), I (etkileri sipariş önlemek için ileri ve geri testleri çalıştırır) Aşağıdaki senaryoyu koştum:
SETUP='import itertools
import random
n=1000000
random.seed(0)
A = [random.randrange(1<<30) for _ in xrange(n)]
B = [random.randrange(1<<30) for _ in xrange(n)]
C = [random.randrange(1<<30) for _ in xrange(n)]'
python -m timeit -s "$SETUP" 'set(A+B+C)'
python -m timeit -s "$SETUP" 's = set(A); s.update(B); s.update(C)'
python -m timeit -s "$SETUP" 's = set(itertools.chain(A,B,C))'
python -m timeit -s "$SETUP" 's = set(itertools.chain(A,B,C))'
python -m timeit -s "$SETUP" 's = set(A); s.update(B); s.update(C)'
python -m timeit -s "$SETUP" 'set(A+B+C)'
ve elde aşağıdaki sonuçlar:
10 loops, best of 3: 579 msec per loop
10 loops, best of 3: 726 msec per loop
10 loops, best of 3: 775 msec per loop
10 loops, best of 3: 761 msec per loop
10 loops, best of 3: 737 msec per loop
10 loops, best of 3: 555 msec per loop
Şimdi set(A+B+C)
açıkça hızlı ve sonuçlar oldukça stabl olan e - bu, sadece ölçüm hatasına kadar yazmak zor. Bu betiği çalıştırmak tekrar tekrar benzer sonuçlar üretir.
yapabilirim sadece tahmin olduğunu bilinen bir uzunluğa sahip olan liste, ve belki de kümelenmiş yapı, başlangıçta yatan bellek gereksinimini daha hassas bir şekilde seçebilir; diğer ikisi kümenin iki kez oluşturulduğu ve yeniden boyutlandırılacağı (ikinci durum) veya potansiyel olarak yeniden boyutlandırıldığı bir yineleyici ile oluşturulabilir arası Neredeyse birçok kez. –
"set_init" değişmedikçe, böyle görünmüyor. ['set_init'] (http://svn.python.org/projects/python/trunk/Objects/setobject.c) sadece düz bir şekilde" set_update_internal "olarak adlandırılır ve sadece elemanların üzerinden geçer. (Ben hg.python.org 'dan çekiyorum ama o sunucu şu anda aşağı görünüyor) – nneonneo
related: [Python'da iki sıralı liste birleştiriliyor] (http://stackoverflow.com/a/482848/4279) – jfs