Réponses:
En Python 2.x:
range
crée une liste, donc si vous le faites, range(1, 10000000)
il crée une liste en mémoire avec des 9999999
éléments.
xrange
est un objet séquence qui évalue paresseusement.
En Python 3, range
fait l'équivalent de python xrange
, et pour obtenir la liste, vous devez utiliser list(range(...))
.
xrange(x).__iter__()
est un générateur.
i
est évalué à la demande plutôt qu'à l'initialisation.
range crée une liste, donc si vous le faites,
range(1, 10000000)
il crée une liste en mémoire avec des9999999
éléments.
xrange
est un générateur, c'estdonc un objet séquence quiestévalué paresseusement.
C'est vrai, mais en Python 3, .range()
sera implémenté par Python 2 .xrange()
. Si vous devez réellement générer la liste, vous devrez faire:
list(range(1,100))
xrange
un générateur? Il s'agit d'une fonction contenant une yield
instruction et, selon le glossaire, ces fonctions sont appelées générateurs.
N'oubliez pas, utilisez le timeit
module pour tester lequel des petits extraits de code est plus rapide!
$ python -m timeit 'for i in range(1000000):' ' pass'
10 loops, best of 3: 90.5 msec per loop
$ python -m timeit 'for i in xrange(1000000):' ' pass'
10 loops, best of 3: 51.1 msec per loop
Personnellement, j'utilise toujours .range()
, sauf si j'ai affaire à des listes vraiment énormes - comme vous pouvez le voir, en termes de temps, pour une liste d'un million d'entrées, la surcharge supplémentaire n'est que de 0,04 seconde. Et comme Corey le fait remarquer, dans Python 3.0 .xrange()
disparaîtra et .range()
vous donnera quand même un bon comportement d'itérateur.
python -m timeit "for i in xrange(1000000):" " pass"
the extra overhead is only 0.04 seconds
n'est pas la bonne façon de la voir, elle (90.5-51.1)/51.1 = 1.771 times slower
est correcte car elle indique que si c'est la boucle principale de votre programme, elle peut potentiellement la goulot d'étranglement. Cependant, si c'est une petite partie, alors 1,77x n'est pas beaucoup.
xrange
stocke uniquement les paramètres de plage et génère les nombres à la demande. Cependant, l'implémentation C de Python limite actuellement ses arguments aux longs C:
xrange(2**32-1, 2**32+1) # When long is 32 bits, OverflowError: Python int too large to convert to C long
range(2**32-1, 2**32+1) # OK --> [4294967295L, 4294967296L]
Notez que dans Python 3.0 il y en a seulement range
et il se comporte comme le 2.x xrange
mais sans les limitations sur les points de fin minimum et maximum.
xrange renvoie un itérateur et ne conserve qu'un seul numéro en mémoire à la fois. range conserve la liste complète des nombres en mémoire.
xrange
ne renvoie pas d'itérateur.
and only keeps one number in memory at a time
et où les autres sont placés, veuillez me guider ..
Passez un peu de temps avec la référence de la bibliothèque . Plus vous le connaissez, plus vite vous pouvez trouver des réponses à des questions comme celle-ci. Les premiers chapitres sur les objets et types intégrés sont particulièrement importants.
L'avantage du type xrange est qu'un objet xrange prendra toujours la même quantité de mémoire, quelle que soit la taille de la plage qu'il représente. Il n'y a aucun avantage de performance cohérent.
Une autre façon de trouver des informations rapides sur une construction Python est la docstring et la fonction d'aide:
print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
Je suis choqué que personne ne lise le doc :
Cette fonction est très similaire à
range()
, mais renvoie unxrange
objet au lieu d'une liste. Il s'agit d'un type de séquence opaque qui donne les mêmes valeurs que la liste correspondante, sans les stocker toutes simultanément. L'avantage dexrange()
overrange()
est minime (car il fautxrange()
toujours créer les valeurs quand on les demande) sauf lorsqu'une très grande plage est utilisée sur une machine affamée de mémoire ou lorsque tous les éléments de la plage ne sont jamais utilisés (comme lorsque la boucle est se termine généralement parbreak
).
range crée une liste, donc si vous faites range (1, 10000000) il crée une liste en mémoire avec 10000000 éléments. xrange est un générateur, il est donc évalué paresseusement.
Cela vous apporte deux avantages:
MemoryError
.Vous trouverez l'avantage de xrange
over range
dans cet exemple simple:
import timeit
t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
pass
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 4.49153590202 seconds
t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
pass
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 7.04547905922 seconds
L'exemple ci-dessus ne reflète rien de mieux en cas de xrange
.
Maintenant, regardez le cas suivant où range
est vraiment très lent par rapport à xrange
.
import timeit
t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
if i == 10000:
break
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 0.000764846801758 seconds
t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
if i == 10000:
break
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 2.78506207466 seconds
Avec range
, il crée déjà une liste de 0 à 100000000 (chronophage), mais xrange
est un générateur et il ne génère que des nombres en fonction du besoin, c'est-à-dire si l'itération se poursuit.
En Python-3, l'implémentation de la range
fonctionnalité est la même que celle de xrange
Python-2, alors qu'elles ont été supprimées xrange
en Python-3
Codage heureux !!
C'est pour des raisons d'optimisation.
range () créera une liste de valeurs du début à la fin (0 .. 20 dans votre exemple). Cela deviendra une opération coûteuse sur de très grandes gammes.
xrange () d'autre part est beaucoup plus optimisé. il ne calculera la valeur suivante qu'en cas de besoin (via un objet de séquence xrange) et ne créera pas une liste de toutes les valeurs comme le fait range ().
range(x,y)
renvoie une liste de chaque nombre entre x et y si vous utilisez une for
boucle, puis range
est plus lent. En fait, range
a une plus grande plage d'index. range(x.y)
imprimera une liste de tous les nombres entre x et y
xrange(x,y)
renvoie xrange(x,y)
mais si vous avez utilisé une for
boucle, alors xrange
c'est plus rapide. xrange
a une plage d'index plus petite. xrange
imprimera non seulement, xrange(x,y)
mais il conservera tous les numéros qui s'y trouvent.
[In] range(1,10)
[Out] [1, 2, 3, 4, 5, 6, 7, 8, 9]
[In] xrange(1,10)
[Out] xrange(1,10)
Si vous utilisez une for
boucle, cela fonctionnerait
[In] for i in range(1,10):
print i
[Out] 1
2
3
4
5
6
7
8
9
[In] for i in xrange(1,10):
print i
[Out] 1
2
3
4
5
6
7
8
9
Il n'y a pas beaucoup de différence lors de l'utilisation de boucles, bien qu'il y ait une différence lors de l'impression!
range (): range (1, 10) renvoie une liste de 1 à 10 chiffres et conserve toute la liste en mémoire.
xrange (): comme range (), mais au lieu de renvoyer une liste, retourne un objet qui génère les nombres dans la plage à la demande. Pour le bouclage, c'est légèrement plus rapide que range () et plus efficace en mémoire. xrange () objet comme un itérateur et génère les nombres à la demande. (Évaluation paresseuse)
In [1]: range(1,10)
Out[1]: [1, 2, 3, 4, 5, 6, 7, 8, 9]
In [2]: xrange(10)
Out[2]: xrange(10)
In [3]: print xrange.__doc__
xrange([start,] stop[, step]) -> xrange object
Certaines des autres réponses mentionnent que Python 3 a éliminé 2.x range
et renommé 2.x xrange
en range
. Cependant, à moins que vous n'utilisiez 3.0 ou 3.1 (ce que personne ne devrait être), c'est en fait un type quelque peu différent.
Comme le disent les documents 3.1 :
Les objets de plage ont très peu de comportement: ils ne prennent en charge que l'indexation, l'itération et la
len
fonction.
Cependant, dans 3.2+, range
est une séquence complète - il prend en charge les tranches étendues, et toutes les méthodes de collections.abc.Sequence
avec la même sémantique que a list
. *
Et, au moins dans CPython et PyPy (les deux implémentations 3.2+ qui existent actuellement), il a également mises en œuvre à temps constant des index
et count
méthodes et l' in
opérateur (aussi longtemps que vous passez seulement elle entiers). Cela signifie que l'écriture 123456 in r
est raisonnable en 3.2+, alors qu'en 2.7 ou 3.1 ce serait une idée horrible.
* Le fait que les issubclass(xrange, collections.Sequence)
retours True
en 2.6-2.7 et 3.0-3.1 est un bug qui a été corrigé dans 3.2 et non rétroporté.
En python 2.x
range (x) renvoie une liste, qui est créée en mémoire avec x éléments.
>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]
xrange (x) renvoie un objet xrange qui est un générateur obj qui génère les nombres à la demande. ils sont calculés pendant for-loop (Lazy Evaluation).
Pour le bouclage, c'est légèrement plus rapide que range () et plus efficace en mémoire.
>>> b = xrange(5)
>>> b
xrange(5)
xrange()
n'est pas un générateur. xrange(n)
.__ iter __ () `est.
Lors du test de gamme contre xrange dans une boucle (je sais que je devrais utiliser timeit , mais cela a été rapidement piraté depuis la mémoire en utilisant un exemple de compréhension de liste simple), j'ai trouvé ce qui suit:
import time
for x in range(1, 10):
t = time.time()
[v*10 for v in range(1, 10000)]
print "range: %.4f" % ((time.time()-t)*100)
t = time.time()
[v*10 for v in xrange(1, 10000)]
print "xrange: %.4f" % ((time.time()-t)*100)
qui donne:
$python range_tests.py
range: 0.4273
xrange: 0.3733
range: 0.3881
xrange: 0.3507
range: 0.3712
xrange: 0.3565
range: 0.4031
xrange: 0.3558
range: 0.3714
xrange: 0.3520
range: 0.3834
xrange: 0.3546
range: 0.3717
xrange: 0.3511
range: 0.3745
xrange: 0.3523
range: 0.3858
xrange: 0.3997 <- garbage collection?
Ou, en utilisant xrange dans la boucle for:
range: 0.4172
xrange: 0.3701
range: 0.3840
xrange: 0.3547
range: 0.3830
xrange: 0.3862 <- garbage collection?
range: 0.4019
xrange: 0.3532
range: 0.3738
xrange: 0.3726
range: 0.3762
xrange: 0.3533
range: 0.3710
xrange: 0.3509
range: 0.3738
xrange: 0.3512
range: 0.3703
xrange: 0.3509
Mes extraits de code sont-ils correctement testés? Des commentaires sur l'instance plus lente de xrange? Ou un meilleur exemple :-)
xrange
semblait légèrement plus rapide, bien qu'avec Python 3 la comparaison soit maintenant redondante.
timeit
. Il prend soin de fonctionner plusieurs fois, de désactiver le GC, d'utiliser la meilleure horloge au lieu de time
, etc.
xrange () et range () en python fonctionnent de la même manière que pour l'utilisateur, mais la différence vient lorsque nous parlons de la façon dont la mémoire est allouée en utilisant à la fois la fonction.
Lorsque nous utilisons range (), nous allouons de la mémoire à toutes les variables qu'il génère, il n'est donc pas recommandé d'utiliser avec un plus grand no. de variables à générer.
xrange (), quant à lui, ne génère qu'une valeur particulière à la fois et ne peut être utilisé qu'avec la boucle for pour imprimer toutes les valeurs requises.
plage génère la liste entière et la renvoie. xrange ne le fait pas - il génère les numéros de la liste à la demande.
Quelle?
range
renvoie une liste statique lors de l'exécution.
xrange
renvoie un object
(qui agit comme un générateur, bien qu'il n'en soit certainement pas un) à partir duquel les valeurs sont générées au fur et à mesure des besoins.
Quand utiliser quoi?
xrange
si vous voulez générer une liste pour une gamme gigantesque, disons 1 milliard, surtout lorsque vous avez un "système sensible à la mémoire" comme un téléphone portable.range
si vous souhaitez parcourir plusieurs fois la liste.PS: Python 3.x de range
fonction == Python 2.x xrange
fonction.
xrange
ne renvoie pas d'objet générateur.
Tout le monde l'a beaucoup expliqué. Mais je voulais qu'il le voie par moi-même. J'utilise python3. J'ai donc ouvert le moniteur de ressources (sous Windows!) Et j'ai d'abord exécuté la commande suivante:
a=0
for i in range(1,100000):
a=a+i
puis vérifié la modification dans la mémoire «En cours d'utilisation». C'était insignifiant. Ensuite, j'ai exécuté le code suivant:
for i in list(range(1,100000)):
a=a+i
Et il a fallu une grande partie de la mémoire pour l'utiliser, instantanément. Et j'étais convaincu. Vous pouvez l'essayer par vous-même.
Si vous utilisez Python 2X, remplacez 'range ()' par 'xrange ()' dans le premier code et 'list (range ())' par 'range ()'.
À partir des documents d'aide.
Python 2.7.12
>>> print range.__doc__
range(stop) -> list of integers
range(start, stop[, step]) -> list of integers
Return a list containing an arithmetic progression of integers.
range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
When step is given, it specifies the increment (or decrement).
For example, range(4) returns [0, 1, 2, 3]. The end point is omitted!
These are exactly the valid indices for a list of 4 elements.
>>> print xrange.__doc__
xrange(stop) -> xrange object
xrange(start, stop[, step]) -> xrange object
Like range(), but instead of returning a list, returns an object that
generates the numbers in the range on demand. For looping, this is
slightly faster than range() and more memory efficient.
Python 3.5.2
>>> print(range.__doc__)
range(stop) -> range object
range(start, stop[, step]) -> range object
Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).
>>> print(xrange.__doc__)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'xrange' is not defined
La différence est apparente. En Python 2.x, range
retourne une liste, xrange
retourne un objet xrange qui est itérable.
Dans Python 3.x, range
devient xrange
Python 2.x et xrange
est supprimé.
Sur une exigence de numérisation / impression d'éléments 0-N, la plage et la plage x fonctionnent comme suit.
range () - crée une nouvelle liste dans la mémoire et prend l'ensemble de 0 à N éléments (totalement N + 1) et les imprime. xrange () - crée une instance d'itérateur qui parcourt les éléments et ne conserve que l'élément actuellement rencontré dans la mémoire, utilisant ainsi la même quantité de mémoire tout le temps.
Dans le cas où l'élément requis se trouve quelque peu au début de la liste, il économise beaucoup de temps et de mémoire.
xrange
ne crée pas d'instance d'itérateur. Il crée un xrange
objet, qui est itérable, mais pas un itérateur - presque (mais pas tout à fait) une séquence, comme une liste.
Range renvoie une liste tandis que xrange renvoie un objet xrange qui prend la même mémoire quelle que soit la taille de la plage, car dans ce cas, un seul élément est généré et disponible par itération alors qu'en cas d'utilisation de la plage, tous les éléments sont générés en même temps et sont disponibles dans la mémoire.
La différence diminue pour les arguments plus petits à range(..)
/ xrange(..)
:
$ python -m timeit "for i in xrange(10111):" " for k in range(100):" " pass"
10 loops, best of 3: 59.4 msec per loop
$ python -m timeit "for i in xrange(10111):" " for k in xrange(100):" " pass"
10 loops, best of 3: 46.9 msec per loop
Dans ce cas, xrange(100)
c'est seulement environ 20% plus efficace.
range: -range remplira tout à la fois, ce qui signifie que chaque numéro de la gamme occupera la mémoire.
xrange: -xrange est quelque chose comme un générateur, il apparaît dans l'image lorsque vous voulez la plage de nombres mais vous ne voulez pas qu'ils soient stockés, comme lorsque vous voulez utiliser la mémoire de loop.so de manière efficace.
De plus, if do list(xrange(...))
sera équivalent à range(...)
.
C'est donc list
lent.
Aussi xrange
ne termine pas vraiment complètement la séquence
Voilà pourquoi ce n'est pas une liste, c'est un xrange
objet
range()
en Python 2.x
Cette fonction est essentiellement l'ancienne range()
fonction qui était disponible en Python 2.x
et renvoie une instance d'un list
objet qui contient les éléments dans la plage spécifiée.
Cependant, cette implémentation est trop inefficace lorsqu'il s'agit d'initialiser une liste avec une plage de nombres. Par exemple, for i in range(1000000)
serait une commande très coûteuse à exécuter, à la fois en termes de mémoire et d'utilisation du temps car elle nécessite le stockage de cette liste dans la mémoire.
range()
en Python 3.x
et xrange()
en Python2.x
Python a 3.x
introduit une nouvelle implémentation de range()
(alors que la nouvelle implémentation était déjà disponible en Python 2.x
via lexrange()
fonction).
Le range()
exploite une stratégie connue sous le nom d' évaluation paresseuse. Au lieu de créer une énorme liste d'éléments dans la plage, la nouvelle implémentation introduit la classe range
, un objet léger qui représente les éléments requis dans la plage donnée, sans les stocker explicitement en mémoire (cela peut ressembler à des générateurs mais le concept d'évaluation paresseuse est différent).
À titre d'exemple, considérons les éléments suivants:
# Python 2.x
>>> a = range(10)
>>> type(a)
<type 'list'>
>>> b = xrange(10)
>>> type(b)
<type 'xrange'>
et
# Python 3.x
>>> a = range(10)
>>> type(a)
<class 'range'>
Voir cet article pour trouver la différence entre la plage et xrange:
Citer:
range
renvoie exactement ce que vous pensez: une liste d'entiers consécutifs, d'une longueur définie commençant par 0.xrange
, cependant, retourne un "objet xrange" , qui agit beaucoup comme un itérateur
xrange
n'est pas un itérateur. La liste renvoyée par range
prend en charge l'itération (une liste est à peu près l'exemple prototypique d'un itérable). L'avantage global de xrange
n'est pas "minime". Etc.