Python: üreteç ifadesi vs verim
Python, orada bir jeneratör aracılığıyla bir nesne yaratmak arasında herhangi bir fark yokturüreteç ifadesikullanarak karşıverimdeyim?
Kullanarakverim:
def Generator(x, y):
for i in xrange(x):
for j in xrange(y):
yield(i, j)
Kullanaraküreteç ifadesi:
def Generator(x, y):
return ((i, j) for i in xrange(x) for j in xrange(y))
Her iki fonksiyon dizilerini, örneğin (0,0) üreten dönüş jeneratör nesneleri (0,1) vb.
Başka biri veya herhangi bir avantaj mı? Düşünceler?
Teşekkürler Millet! Bu cevaplar içinde büyük bilgi ve diğer kaynaklar bir sürü var!
CEVAP
Sadece iki ufak farklar vardır. Kendiniz için bu tarz bir şeyi incelemek dis
modülünü kullanabilirsiniz.
Düzenleme:Benim ilk sürümü etkileşimli istemi jeneratör ifadesi modül kapsamında oluşturulan decompiled. Bununla OP versiyonu bir işlev içinde kullanılan biraz farklı. Bu soru gerçek bir eşleşme için modifiye ettim.
Gördüğünüz gibi aşağıda, "verim" jeneratör (ilk durum) üç ilave talimatlar Kur, ama ilk FOR_ITER
farklı sadece bir saygı: "verim" bir yaklaşım kullanır LOAD_FAST
yer LOAD_DEREF
döngünün içinde. LOAD_DEREF
"rather slower" LOAD_FAST
, öyle yapar "verim" sürüm biraz daha hızlı jeneratör ifade için yeterince büyük değerler x
(dış döngü) çünkü değeri y
yüklü biraz daha hızlı üzerinde her geçişte. x
küçük değerler için kurulum kodu ek yükü nedeniyle biraz daha yavaş olacaktır.
Ayrıca değer jeneratör ifadesi genelde böyle işlevi ile kaydırma yerine kod içinde satır içi kullanılan olacağını işaret olabilir. Kur yükü biraz kaldırın ve jeneratör LOAD_FAST
"" sürüm bir avantajı yoksa. verim verse bile biraz daha hızlı, daha küçük döngü değerleri ifade eder
Her iki durumda da ki performans farkı ya da diğeri arasında karar haklı çıkarmak için yeterli. Okunabilirlik el kadar kullanmak en okunabilir duruma geliyor, hangisi daha önemli.
>>> def Generator(x, y):
... for i in xrange(x):
... for j in xrange(y):
... yield(i, j)
...
>>> dis.dis(Generator)
2 0 SETUP_LOOP 54 (to 57)
3 LOAD_GLOBAL 0 (xrange)
6 LOAD_FAST 0 (x)
9 CALL_FUNCTION 1
12 GET_ITER
>> 13 FOR_ITER 40 (to 56)
16 STORE_FAST 2 (i)
3 19 SETUP_LOOP 31 (to 53)
22 LOAD_GLOBAL 0 (xrange)
25 LOAD_FAST 1 (y)
28 CALL_FUNCTION 1
31 GET_ITER
>> 32 FOR_ITER 17 (to 52)
35 STORE_FAST 3 (j)
4 38 LOAD_FAST 2 (i)
41 LOAD_FAST 3 (j)
44 BUILD_TUPLE 2
47 YIELD_VALUE
48 POP_TOP
49 JUMP_ABSOLUTE 32
>> 52 POP_BLOCK
>> 53 JUMP_ABSOLUTE 13
>> 56 POP_BLOCK
>> 57 LOAD_CONST 0 (None)
60 RETURN_VALUE
>>> def Generator_expr(x, y):
... return ((i, j) for i in xrange(x) for j in xrange(y))
...
>>> dis.dis(Generator_expr.func_code.co_consts[1])
2 0 SETUP_LOOP 47 (to 50)
3 LOAD_FAST 0 (.0)
>> 6 FOR_ITER 40 (to 49)
9 STORE_FAST 1 (i)
12 SETUP_LOOP 31 (to 46)
15 LOAD_GLOBAL 0 (xrange)
18 LOAD_DEREF 0 (y)
21 CALL_FUNCTION 1
24 GET_ITER
>> 25 FOR_ITER 17 (to 45)
28 STORE_FAST 2 (j)
31 LOAD_FAST 1 (i)
34 LOAD_FAST 2 (j)
37 BUILD_TUPLE 2
40 YIELD_VALUE
41 POP_TOP
42 JUMP_ABSOLUTE 25
>> 45 POP_BLOCK
>> 46 JUMP_ABSOLUTE 6
>> 49 POP_BLOCK
>> 50 LOAD_CONST 0 (None)
53 RETURN_VALUE
Atama lambda ifadesi içinde Python...
Python "" ifadesi bir try-ex...
Verim anahtar kelime Python ne yapar?...
Uygulamada, yeni "" verim; Py...
%S Python ne demek?...