2013-12-10 6 views
12

Q1 - Ist die folgenden ein set() ein generator expression oder set comprehension? (Oder sind sie gleich, wenn dem so ist, sind list & dict Comprehensions auch entsprechenden Typs Guss auf Generatoren?)Wie funktionieren Python-Set-Beschreibungen?

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

Q2 - Ist die Auswertung betrachten doppelte Werte & sie dann entfernen, indem set() Anwendung?

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

Hat das Verständnis (Speed-weise) besser als herkömmliche for Schleifen durchführen?

Update - Ich habe versucht timeit für Geschwindigkeitsvergleiche. Bin mir nicht sicher, ob ich nur (fair) darüber bin.

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 

nun einige conditionals mit

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 

So gibt es einige recht Unterschied, ist es aufgrund der Funktionalität in c fest einprogrammiert werden?

+1

Vielleicht könnten Sie timeit (http://docs.python.org/2/library/timeit.html) verwenden oder eine Code-Timing-Funktion mit dem Zeitmodul erstellen, um die in 'C geschriebenen Zeit-/Geschwindigkeitsdifferenzen – Totem

Antwort

7

Q1: Ja, ja, ja und ja. Oder zumindest verhalten sie sich so. Es ist ein bisschen anders, wenn Sie sich den Bytecode ansehen. Lassen Sie uns diesen Code zerlegen (Python 2.7):

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) 

Das ist, was man bekommt:

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      

Der Bytecode für die dict comprenhension, die Menge Verständnis und den Generator kaum gleich ist. Sie laden alle ein Codeobjekt (<dictcomp>, <setcomp> oder <genexpr>) und machen dann eine aufrufbare Funktion daraus. Das Listenverständnis ist anders, weil es den Bytecode erzeugt, der Ihrem Listenverständnis entspricht. Diesmal wird es interpretiert und ist somit nicht nativ.

Q2: Es ist nicht wirklich in Betracht zieht doppelte Werte, da es ein Verständnis mit der Liste erstellt Sie gaben. Und dann schafft es das Set mit dem Verständnis.

Über das Timing: List/Dict/Set Comprehensions neigen dazu, schneller als alles andere zu sein. Selbst wenn sie interpretiert werden, ist der erzeugte Bytecode für die meisten Fälle mit speziellen Bytecode-Anweisungen wie SET_ADD, LIST_APPEND oder MAP_ADD optimiert.

+0

herauszufinden '?? –

+0

Ich bin mir nicht sicher, ich werde das überprüfen. – Vincent

+3

offensichtlich, was es geschrieben wird hängt davon ab, welche Python Sie verwenden (CPython, IronPython, Jython, PyPy, etc). der wichtige Punkt ist jedoch, dass es _native_ d. h. nicht interpretiert wird. –