Questo question e il mio answer mi hanno fatto riflettere su questa particolare differenza tra Python 2.7 e Python 3.4. Prendete il codice di esempio semplice:L'affettatura è molto più lenta in Python 3.4?
import timeit
import dis
c = 1000000
r = range(c)
def slow():
for pos in range(c):
r[pos:pos+3]
dis.dis(slow)
time = timeit.Timer(lambda: slow()).timeit(number=1)
print('%3.3f' % time)
In Python 2.7, ho sempre arrivare 0.165~
e per Python 3.4 ho sempre capito 0.554~
. L'unica differenza significativa tra i disassemblaggi è che Python 2.7 emette il codice byte SLICE+3
mentre Python 3.4 emette BUILD_SLICE
seguito da BINARY_SUBSCR
. Nota che ho eliminato i candidati per un potenziale rallentamento dall'altra domanda, vale a dire le stringhe e il fatto che xrange
non esiste in Python 3.4 (che dovrebbe essere comunque simile alla classe range
di quest'ultimo).
Utilizzare itertools'
islice
produce tempi quasi identici tra i due, quindi ho il forte sospetto che sia l'affettatura che è la causa della differenza qui.
Perché sta succedendo questo e c'è un collegamento a una fonte autorevole che documenta un cambiamento nel comportamento?
MODIFICA: in risposta alla risposta, ho spostato gli oggetti range
in list
, che ha dato un notevole aumento di velocità. Tuttavia, poiché ho aumentato il numero di iterazioni in timeit
, ho notato che le differenze di temporizzazione sono diventate sempre più grandi. Come controllo di integrità, ho sostituito l'affettamento con None
per vedere cosa sarebbe successo.
500 iterazioni in timeit
.
c = 1000000
r = list(range(c))
def slow():
for pos in r:
None
cede rispettivamente 10.688
e 9.915
. La sostituzione del ciclo for con for pos in islice(r, 0, c, 3)
produce rispettivamente 7.626
e 6.270
. La sostituzione di None
con r[pos]
ha prodotto rispettivamente 20~
e 28~
. r[pos:pos+3]
produce rispettivamente 67.531
e 106.784
.
Come potete vedere, le differenze di temporizzazione sono enormi. Ancora una volta, sono ancora convinto che il problema non sia direttamente correlato a range
.
Stavi usando 'range' o' xrange' in Python 2? – cdarke
Riprovare con 'r = list (range (c))'. –
Gli oggetti Python 3 'range' e Python 2' xrange' non sono simili in questo contesto. Gli oggetti Python 3 'range' supportano l'slicing, gli oggetti Python 2' xrange' non supportano l'slicing. – cdarke