2014-04-01 20 views
14

Warum ist das Flachkopieren einer Liste mit einem Schnitt so viel schneller als die Verwendung von list?Warum wird eine Liste mit einem Schnitt [:] schneller kopiert als mit der offensichtlichen Methode?

In [1]: x = range(10) 

In [2]: timeit x_ = x[:] 
10000000 loops, best of 3: 83.2 ns per loop 

In [3]: timeit x_ = list(x) 
10000000 loops, best of 3: 147 ns per loop 

Normalerweise, wenn ich seltsame Dinge wie diese sehen, sind sie in python3 fixiert - aber diese Diskrepanz ist immer noch da:

In [1]: x = list(range(10)) 

In [2]: timeit x_ = x[:] 
10000000 loops, best of 3: 100 ns per loop 

In [3]: timeit x_ = list(x) 
10000000 loops, best of 3: 178 ns per loop 
+0

bezogen auf http://stackoverflow.com/questions/12537716/why-is-slice-assignment-faster-than-list-insert?rq=1 – njzk2

+0

Eine Erklärung dafür ist, dass 'list' eine Funktion ist, dass Sie müssen anrufen. – njzk2

+0

Liste muss auch Sachen mit jedem Gegenstand machen, wo ein Schnitt nur einen Speicherblock an eine neue Adresse kopiert ... –

Antwort

9

Der Unterschied in der zusätzlichen Funktionsaufruf (nur SLICE+0 vs CALL_FUNCTION 1 mit zusätzliche Stapeloperationen):

>>> import dis 
>>> def f(lst): 
... return lst[:] 
... 
>>> def f1(lst): 
... return list(lst) 
... 
>>> dis.dis(f) 
    2   0 LOAD_FAST    0 (lst) 
       3 SLICE+0    
       4 RETURN_VALUE   
>>> dis.dis(f1) 
    2   0 LOAD_GLOBAL    0 (list) 
       3 LOAD_FAST    0 (lst) 
       6 CALL_FUNCTION   1 
       9 RETURN_VALUE 

Von dis docs:

SLICE + 0()
Implementiert TOS = TOS [:].

(TOS - oben auf dem Stack)

CALL_FUNCTION (arge)
Ruft eine Funktion. Das Low-Byte von argc gibt die Anzahl der Positionsparameter, das High-Byte die Anzahl der Schlüsselwortparameter an. Auf dem Stapel findet der Opcode zuerst das Schlüsselwort Parameter. Für jedes Schlüsselwortargument steht der Wert über der Schlüssel. Unterhalb der Schlüsselwortparameter befinden sich die Positionsparameter auf dem Stapel, wobei der Parameter ganz rechts oben liegt. Unterhalb der Parameter befindet sich das zu rufende Funktionsobjekt auf dem Stapel. Gibt alle Funktionsargumente und die Funktion selbst aus dem Stapel und drückt den Rückgabewert.