2013-12-10 31 views
12

Q1 - Aşağıdaki set(), generator expression veya set comprehension mu? (Ya da Eğer öyleyse, aynı olan list & dict comprehensions da karşılık gelen tip döküm jeneratörlerde?)Python Set Comprehensions nasıl çalışır?

my_set = {x for x in range(10)} 

Q2 - değerlendirme yinelenen değerler & sonra set() uygulayarak bunları kaldırmak düşünün mu?

dup_set = {x for x in [0, 1, 2, 0, 1, 2]} 

anlama gerçekleştirmek mu (hız-bilge) düzenli for döngüler daha iyi?

Güncelleştirme - Hız karşılaştırmaları için timeit numaralı telefonu kullanmayı denedim. Ben bu konuda sadece (adil) olduğumdan emin değilim. Bazı conditionals

kullanarak Şimdi
C:\>python -m timeit "s = set()" "for x in range(10):" " 
    s.add(x)" 
100000 loops, best of 3: 2.3 usec per loop 

C:\>python -m timeit "s = {x for x in range(10)}" 
1000000 loops, best of 3: 1.68 usec per loop 

,
C:\>python -m timeit "s = set()" "for x in range(10):" " 
    if x%2: s.add(x)" 
100000 loops, best of 3: 2.27 usec per loop 

C:\>python -m timeit "s = {x for x in range(10) if x%2}" 
1000000 loops, best of 3: 1.83 usec per loop 

Yani, orada oldukça fark vardır o c kodlanmış olan işlevselliği nedeniyle?

+1

Belki de timeit (http://docs.python.org/2/library/timeit.html) kullanabilir veya "C" ile yazılan zaman/hız farklarını ( – Totem

cevap

7

S1: Evet, evet, evet ve evet. Ya da en azından böyle davranırlar. Baytkodu incelemeniz biraz farklıdır. en (Python 2.7) bu kodu söktüğünüzde edelim:

def list_comp(l): 
    return [x+1 for x in l] 

def dict_comp(l): 
    return {x+1:0 for x in l} 

def set_comp(l): 
    return {x+1 for x in l} 

def generator(l): 
    return (x+1 for x in l) 

Bu ne elde ediyoruz:

Disassembly of list_comp: 
    2   0 BUILD_LIST    0 
       3 LOAD_FAST    0 (l) 
       6 GET_ITER    
     >> 7 FOR_ITER    16 (to 26) 
      10 STORE_FAST    1 (x) 
      13 LOAD_FAST    1 (x) 
      16 LOAD_CONST    1 (1) 
      19 BINARY_ADD   
      20 LIST_APPEND    2 
      23 JUMP_ABSOLUTE   7 
     >> 26 RETURN_VALUE 
Disassembly of dict_comp: 
    5   0 LOAD_CONST    1 (<code object <dictcomp> at 029DEE30) 
       3 MAKE_FUNCTION   0 
       6 LOAD_FAST    0 (l) 
       9 GET_ITER    
      10 CALL_FUNCTION   1 
      13 RETURN_VALUE 
Disassembly of set_comp: 
    8   0 LOAD_CONST    1 (<code object <setcomp> at 029DECC8) 
       3 MAKE_FUNCTION   0 
       6 LOAD_FAST    0 (l) 
       9 GET_ITER    
      10 CALL_FUNCTION   1 
      13 RETURN_VALUE 
Disassembly of generator: 
11   0 LOAD_CONST    1 (<code object <genexpr> at 02A8FD58) 
       3 MAKE_FUNCTION   0 
       6 LOAD_FAST    0 (l) 
       9 GET_ITER    
      10 CALL_FUNCTION   1 
      13 RETURN_VALUE      

baytkodu zorlukla dict comprenhension set anlama ve jeneratör için aynıdır. Hepsi bir kod nesnesi (<dictcomp>, <setcomp> veya <genexpr>) yükler ve daha sonra bunun dışında kalınabilir bir işlev oluşturur. Liste kavraması farklıdır çünkü liste kavramanıza karşılık gelen bayt kodunu üretir. Bu kez yorumlanır ve bu nedenle yerel değildir.

S2: Gerçekten verdiğiniz değerler ile ilgili bir kavrayış oluşturduğundan, yinelenen değerleri dikkate almaz. Ve sonra seti anlama ile yaratır.

Zamanlama hakkında: Liste/Dict/Set anlamaları diğerlerinden daha hızlı olma eğilimindedir. Yorumlanmasalar bile, üretilen bytecode, çoğu durumda SET_ADD, LIST_APPEND veya MAP_ADD gibi özel bytecode komutları ile optimize edilmiştir.

+0

) bulmak için zaman modülüyle bir kod zamanlama fonksiyonu oluşturabilirsiniz. '?? –

+0

Emin değilim, bunu kontrol edeceğim. – Vincent

+3

açıkçası, yazdığınız python'a (CPython, IronPython, Jython, PyPy, vb.) Bağlı olarak değişecektir. bununla birlikte, önemli olan nokta _native_ yani interaktif değildir. –