Recent am inceput sa folosesc Python3 și it's lipsa de xrange doare.
Exemplu simplu:
1) Python2:
from time import time as t
def count():
st = t()
[x for x in xrange(10000000) if x%4 == 0]
et = t()
print et-st
count()
2) Python3:
from time import time as t
def xrange(x):
return iter(range(x))
def count():
st = t()
[x for x in xrange(10000000) if x%4 == 0]
et = t()
print (et-st)
count()
Rezultatele sunt, respectiv:
1) 1.53888392448 2) 3.215819835662842
De ce este asta? Adică, de ce xrange's a fost eliminat? L's astfel un instrument de mare pentru a învăța. Pentru incepatori, ca mine, ca noi toți, la un moment dat. De ce-l eliminați? Poate cineva să-mi punctul de buna PEP, nu pot't găsi.
Noroc.
Unele măsurători de performanță, folosind datănu
în loc de a încerca să-l facă manual cu "timpul".
În primul rând, Apple 2.7.2 64-bit:
In [37]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.05 s per loop
Acum, python.org 3.3.0 64-bit:
In [83]: %timeit collections.deque((x for x in range(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.32 s per loop
In [84]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.31 s per loop
In [85]: %timeit collections.deque((x for x in iter(range(10000000)) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.33 s per loop
Aparent, 3.x "gama" este într-adevăr un pic mai lent decât 2.x xrange
. Și OP's xrange funcția nu are nimic de-a face cu asta. (Nu este de mirare, ca un apel la
iter` slot e't probabil să fie vizibile între 10000000 apeluri la ceea ce se întâmplă în buclă, dar cineva a adus-o ca o posibilitate.)
Dar's doar 30% mai lent. Cum a OP 2x la fel de lent? Ei bine, dacă am repeta aceleași teste cu 32-bit Python, am 1.58 vs 3.12. Deci, părerea mea este că acesta este încă unul dintre acele cazuri în care 3.x a fost optimizat pentru 64-bit de performanță în moduri care doare 32-bit.
Dar chiar conteaza? Verifica acest lucru, cu 3.3.0 64-bit din nou:
In [86]: %timeit [x for x in range(10000000) if x%4 == 0]
1 loops, best of 3: 3.65 s per loop
Deci, construirea "lista" nevoie de mai mult decât de două ori mai mult decât întreaga iterație.
Și, ca și pentru "consumă mult mai multe resurse decât Python 2.6+", din testele mele, se pare ca un 3.x "gama" este exact aceeași dimensiune ca un 2.x xrange
—și, chiar dacă ar fi fost de 10 ori la fel de mare, construirea inutile lista este încă despre 10000000x mai mult o problemă decât orice intervalul de repetare ar fi putut face.
Și ce despre o explicit "pentru" buclă în loc de C buclă în interiorul deque
?
In [87]: def consume(x):
....: for i in x:
....: pass
In [88]: %timeit consume(x for x in range(10000000) if x%4 == 0)
1 loops, best of 3: 1.85 s per loop
Deci, aproape la fel de mult timp pierdut în "pentru" declarație ca și în activitatea reală de iterarea "gama".
Daca're îngrijorat despre optimizarea repetare de o gama obiect,'re, probabil, în locul greșit.
Între timp, mă tot întrebi de ce xrange
a fost eliminat, indiferent de cât de multe ori oamenii vă spun același lucru, dar eu'll repet din nou: nu s-A eliminat: a fost redenumit la "gama", și 2.x "gama" este ceea ce a fost eliminat.
Aici's o dovadă că 3.3 "gama" obiectul este un descendent direct al 2.x xrange
obiect (și nu de 2.x "gama" funcția): sursa 3.3 rază de acțiune
și 2.7 xrange
. Puteți vedea chiar schimba istoria (legate de, cred, o schimbare care a înlocuit ultima instanță a string "xrange" oriunde în fișier).
Deci, de ce este mai lent?
Ei bine, pentru unul, ei'am adăugat o mulțime de noi caracteristici. Pentru altul, ei'am făcut tot felul de modificări peste tot (mai ales în interiorul repetare) care au efecte secundare minore. Și acolo'd fost o mulțime de lucru pentru a dramatic a optimiza diverse cazuri importante, chiar dacă, uneori, ușor pessimizes mai puțin important de cazuri. Adăugați la toate astea, și am'nu m-a surprins că iterarea o rază de acțiune
cât mai repede posibil este acum un pic mai lent. L's unul dintre cele mai importante cazuri pe care nimeni nu i-ar pasa suficient să se concentreze pe. Nimeni nu este de natură să aibă o viața reală caz de utilizare în cazul în care aceasta diferenta de performanta este hotspot în codul lor.
Python3's gamă is Python2's xrange. Nu's nu este nevoie să-și încheie un iter în jurul valorii de ea. Pentru a obține o listă reală în Python3, aveți nevoie pentru a utiliza lista(interval(...))`
Daca vrei ceva care funcționează cu Python2 și Python3, încercați acest lucru
try:
xrange
except NameError:
xrange = range
Python 3's "gama" de tip funcționează la fel ca Python 2's xrange
. Am'm nu sunt sigur de ce ai're a vedea o încetinire, deoarece iterator revenit cu xrange funcția este exact ceea ce ai'd obține dacă ați reiterat peste "gama" direct.
Am'm nu a putut să reproducă încetinire pe sistemul meu. Aici's cum am testat:
Python 2, cu xrange
:
Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)
18.631936646865853
Python 3, cu "gama" este un pic mai repede:
Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)
17.31399508687869
Recent am aflat că Python 3's "gama" tip are unele alte caracteristici îngrijite, cum ar fi suport pentru feliere: raza(10,100,2)[5:25:5]este raza(20, 60, 10)
!
comp:~$ python Python 2.7.6 (implicit, Jun 22 2015, 17:58:13) [GCC 4.8.2] pe linux2
>>> import timeit
>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)
5.656799077987671
>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)
5.579368829727173
>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)
21.54827117919922
>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)
22.014557123184204
Cu datănu număr=1 param:
>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=1)
0.2245171070098877
>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=1)
0.10750913619995117
comp:~$ python3 Python 3.4.3 (implicit, 14 Oct 2015, 20:28:29) [GCC 4.8.4] pe linux
>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)
9.113872020003328
>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)
9.07014398300089
Cu datănu număr=1,2,3,4 param funcționează rapid și în mod liniar:
>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=1)
0.09329321900440846
>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=2)
0.18501482300052885
>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=3)
0.2703447980020428
>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=4)
0.36209142999723554
Deci se pare că dacă vom măsura 1 execută bucla ciclu ca datănu.datănu("[x pentru x în intervalul(1000000) dacă x%4]",numărul=1) (ca ne-am folosi de fapt în codul real) python3 funcționează destul de repede, dar în repetate bucle python 2 xrange() câștigă în viteză împotriva intervalul() din python 3.