Neden geri başka yavaştır erken?
Bu nedenle 30 ** bir soru.Düzenleme:bu soru zaten OP the same question, ama bunun farkında olduğumu sormak için ona yazdım kodu kullanılmış gibi görünüyor. Özür dilerim. Cevaplar verilir farklı olsa da!
Büyük ölçüde fark ettim:
>>> def without_else(param=False):
... if param:
... return 1
... return 0
>>> def with_else(param=False):
... if param:
... return 1
... else:
... return 0
>>> from timeit import Timer as T
>>> T(lambda : without_else()).repeat()
[0.3011460304260254, 0.2866089344024658, 0.2871549129486084]
>>> T(lambda : with_else()).repeat()
[0.27536892890930176, 0.2693932056427002, 0.27011704444885254]
>>> T(lambda : without_else(True)).repeat()
[0.3383951187133789, 0.32756996154785156, 0.3279120922088623]
>>> T(lambda : with_else(True)).repeat()
[0.3305950164794922, 0.32186388969421387, 0.3209099769592285]
...ya da diğer bir deyişle: else
fıkra if
durumu tetikleyen olmanın hızlı olursa olsun sahip veya değil.
Farklı bayt kodunu iki tarafından oluşturulan ilgisi var sanırım, ama kimseye/detaylar teyit edebilir?
DÜZENLEME:Herkes benim sistemi hakkında biraz bilgi vermek yararlı olabileceğini düşündüm bu yüzden benim zamanlamaları üretiyor olması gibi görünüyor. Varsayılan python yüklü 11.10 64 bit Ubuntu koşuyorum. python
aşağıdaki sürüm bilgileri oluşturur:
Python 2.7.2 (default, Oct 4 2011, 20:06:09)
[GCC 4.6.1] on linux2
Burada demontaj Python 2.7: sonuçları
>>> dis.dis(without_else)
2 0 LOAD_FAST 0 (param)
3 POP_JUMP_IF_FALSE 10
3 6 LOAD_CONST 1 (1)
9 RETURN_VALUE
4 >> 10 LOAD_CONST 2 (0)
13 RETURN_VALUE
>>> dis.dis(with_else)
2 0 LOAD_FAST 0 (param)
3 POP_JUMP_IF_FALSE 10
3 6 LOAD_CONST 1 (1)
9 RETURN_VALUE
5 >> 10 LOAD_CONST 2 (0)
13 RETURN_VALUE
14 LOAD_CONST 0 (None)
17 RETURN_VALUE
CEVAP
Bu yalnızca bir tahmin olduğunu ve doğru olup olmadığını kontrol etmek için kolay bir yol bulamadım, ama senin için bir teorim var.
Kodunuzu denedim ve aynı sonuçları without_else()
sürekli with_else()
biraz daha yavaştır
>>> T(lambda : without_else()).repeat()
[0.42015745017874906, 0.3188967452567226, 0.31984281521812363]
>>> T(lambda : with_else()).repeat()
[0.36009842032996175, 0.28962249392031936, 0.2927151355828528]
>>> T(lambda : without_else(True)).repeat()
[0.31709728471076915, 0.3172671387005721, 0.3285821242644147]
>>> T(lambda : with_else(True)).repeat()
[0.30939889008243426, 0.3035132258429485, 0.3046679117038593]
Bayt kodu aynı olduğunu düşünürsek, tek fark fonksiyon adıdır. Özellikle zamanlama testi genel adı üzerinde arama yapar. without_else()
yeniden adlandırma deneyin ve farkı kaybolur:
>>> def no_else(param=False):
if param:
return 1
return 0
>>> T(lambda : no_else()).repeat()
[0.3359846013948413, 0.29025818923918223, 0.2921801513879245]
>>> T(lambda : no_else(True)).repeat()
[0.3810395594970828, 0.2969634408842694, 0.2960104566362247]
Benim tahminim without_else
globals()
başka bir şey ile karma bir çarpışma olduğu genel ad arama biraz daha yavaş.
Edit: 7 veya 8 tuşu ile bir sözlük muhtemelen 32 yuvası var, buna dayanarak without_else
__builtins__
ile karma bir çarpışma vardır:
>>> [(k, hash(k) % 32) for k in globals().keys() ]
[('__builtins__', 8), ('with_else', 9), ('__package__', 15), ('without_else', 8), ('T', 21), ('__name__', 25), ('no_else', 28), ('__doc__', 29)]
Karma nasıl çalıştığını açıklamak için:
__builtins__
modül tablo boyutu azaltan -1196389688 dosyalar (32) Tablo #8 yuvasına saklanır anlamına gelir.
without_else
32 modül azaltan 505688136 için karma bir çarpışma var 8. Bu Python gidermek için hesaplar:
İle başlayan:
j = hash % 32
perturb = hash
Ücretsiz bir yuva bulana kadar bu işlemi tekrarlayın:
j = (5*j) 1 perturb;
perturb >>= 5;
use j % 2**i as the next table index;
bir sonraki dizini olarak kullanmak için 17 verir. Neyse ki bu döngü sadece bir kez tekrarlar çok özgür.
Tabloya her sonda bunlardan birini bulabilirsiniz:
Yuva boş, sondaj durur ve biz biliyoruz bu durumda. değeri tablo değil.
Yuva kullanılmayan ama bu durumda deneyin gidiyoruz eskiden yukarıdaki esaslara göre sonraki değer.
Yuvasına tam ama tam karma değeri tabloda saklanmaz. (o da ne arıyoruz anahtarının karma olarak aynı
__builtins__
vswithout_else
) durumunda olur.Dolmuştur ve tam olarak istediğimiz karma değeri vardır, o zaman Python eğer anahtar ve arıyoruz nesne olup olmadığını denetler aynı nesne, bu durumda, çünkü kısa dizeleri olacak (hangi aynı tanımlayıcılar kullanmak çok staj vardır tanımlayıcıları olabilir dize aynı).
Nihayet dolmuştur, karma tam olarak uyuşuyor, ama anahtarlar aynı nesne değildir, o zaman ve yalnızca o zaman Python çalışacağız eşitlik karşılaştırılması. Bu nispeten yavaş, ama adı aramaları durumunda aslında olmamalı.
Neden baskı "B" baskı " ...
Neden Standart girdiden okuma satır Py...
Neden malloc calloc memset daha yavaşt...
Neden python 'başka' sonra v...
Ne kadar erken bir komisyon görevden g...