Quelle est la différence entre les fonctions range et xrange en Python 2?X?
28 réponses
range crée une liste, donc si vous faites range(1, 10000000)
il crée une liste en mémoire avec des éléments 9999999
.
xrange
est un objet séquentiel qui est évalué paresseusement.
il faut ajouter à partir de l'indice de @Thiago, que dans python3, range fait l'équivalent de xrange de python
range crée une liste, donc si vous faites
range(1, 10000000)
il crée une liste en mémoire avec des éléments9999999
.
xrange
est un générateur, de sorte qu'ilest un objet séquenceest unqui évalue paresseusement.
c'est vrai, mais en Python 3, range sera implémenté par xrange(). Si vous avez besoin de réellement générer la liste, vous aurez besoin de faire:
list(range(1,100))
rappelez-vous, utilisez le module timeit pour tester lequel des petits snipps de code est le 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 je m'occupais de vraiment listes énormes -- comme vous pouvez le voir, le temps-sage, pour une liste d'un million d'entrées, les frais généraux supplémentaires est seulement 0.04 secondes. Et comme Corey le souligne, en Python 3.0 xrange disparaîtra et range vous donnera de toute façon un comportement itérateur agréable.
xrange
stocke seulement les params de gamme et génère les nombres sur demande. Cependant L'implémentation C de Python limite actuellement son args à C longs:
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 qu'en Python 3.0 il n'y a que range
et il se comporte comme le 2.x xrange
, mais sans les limites relatives aux points limites minimal et maximal.
xrange renvoie un itérateur et ne garde qu'un nombre en mémoire à la fois. range garde la liste entière des nombres en mémoire.
Faire passer un peu de temps avec le Librairie de Référence . Plus vous êtes familiarisé avec elle, plus vite vous pouvez trouver des réponses à des questions comme celle-ci. Les premiers chapitres sur les objets et les types de construction sont particulièrement importants.
l'avantage du type xrange est qu'un objet xrange sera toujours prendre la même quantité de mémoire, peu importe la taille de la plage qu'elle représente. Il n'y a pas des performances constantes avantage.
une autre façon de trouver des informations rapides sur une construction Python est le docstring et la fonction d'aide:
print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
range () vs xrange () in python :
range() et xrange () sont deux fonctions qui peuvent être utilisées pour itérer un certain nombre de fois dans les boucles en Python. En Python 3 , Il n'y a pas de xrange, mais la fonction range se comporte comme xrange en Python 2.Si vous voulez écrire du code qui fonctionnera à la fois sur Python 2 et Python 3, vous devez utiliser range().
range() – Cela renvoie une liste de numéros de créé à l'aide de gamme() fonction.
xrange () – cette fonction renvoie l'objet générateur qui peut être utilisé pour afficher des nombres uniquement par boucle. Seule une gamme particulière est affichée sur demande et donc appelée "évaluation paresseuse".
les deux sont mis en œuvre de différentes façons et ont des caractéristiques différentes associées à eux. Les points de comparaison sont:
- Type De Retour De Fonctionnement De La Mémoire Vitesse D'Utilisation
- Mémoire
- Utilisation Opérationnelle
- vitesse
1. Type De Retour:
range() renvoie la liste comme type de retour.
xrange() renvoie xrange() de l'objet.
# initializing a with range()
a = range(1,10000)
# initializing a with xrange()
x = xrange(1,10000)
# testing the type of a
print ("The return type of range() is : ")
print (type(a))
# testing the type of x
print ("The return type of xrange() is : ")
print (type(x))
sortie:
The return type of range() is :
<type 'list'>
The return type of xrange() is :
<type 'xrange'>
2. Mémoire:
la variable stockant la plage créée par range() prend plus de mémoire que la variable stockant la plage en utilisant xrange(). La raison principale est le type de retour de l'objet range() est list et xrange() est xrange ().
# initializing a with range()
a = range(1,10000)
# initializing a with xrange()
x = xrange(1,10000)
# testing the size of a
print ("The size allotted using range() is : ")
print (sys.getsizeof(a))
# testing the size of a
print ("The size allotted using xrange() is : ")
print (sys.getsizeof(x))
sortie:
The size allotted using range() is :
80064
The size allotted using xrange() is :
40
3. Utilisation des opérations:
Que range() retourne la liste de toutes les opérations qui peuvent être appliquées sur la liste peuvent être utilisés. D'autre part, comme xrange() renvoie l'objet xrange, les opérations associées à list ne peuvent pas être appliquées sur eux, donc un inconvénient.
# Python code to demonstrate range() vs xrange()
# on basis of operations usage
# initializing a with range()
a = range(1,6)
# initializing a with xrange()
x = xrange(1,6)
# testing usage of slice operation on range()
print ("The list after slicing using range is : ")
print (a[2:5])
# testing usage of slice operation on xrange()
print ("The list after slicing using xrange is : ")
print (x[2:5])
sortie:
The list after slicing using range is :
[3, 4, 5]
The list after slicing using xrange is :
Traceback (most recent call last):
File "pp.py", line 18, in <module>
print (x[2:5])
TypeError: sequence index must be integer, not 'slice'
4. Vitesse:
en raison du fait que xrange () n'évalue que l'objet générateur contenant seulement les valeurs qui sont exigées par lazy evaluation, est donc plus rapide dans la mise en œuvre que range().
Points Importants:
- si vous voulez écrire du code qui fonctionnera à la fois sur Python 2 et Python 3, Utilisez la plage () car la fonction xrange est dépréciée en Python 3.
- range () est plus rapide si l'itération sur la même séquence multiple temps.
- xrange() doit reconstruire l'objet entier à chaque fois, mais range () aura de vrais objets integer. (Il sera toujours effectuer le pire en termes de mémoire).
gamme crée une liste, donc si vous ne range(1, 10000000), il crée une liste en mémoire avec 10000000 éléments. xrange est un générateur, donc il évalue paresseusement.
cela vous apporte deux avantages:
- vous pouvez itérer des listes plus longues sans obtenir un
MemoryError
. - comme il résout chaque nombre paresseusement, si vous arrêtez itération tôt, vous ne perdrez pas de temps à créer la liste entière.
je suis choqué personne ne lit doc :
cette fonction est très similaire à
range()
, mais renvoie un objetxrange
au lieu d'une liste. Il s'agit d'un type de séquence opaque qui fournit les mêmes valeurs que la liste correspondante, sans les stocker en même temps. L'avantage dexrange()
surrange()
est minime (puisquexrange()
doit encore créer les valeurs lorsqu'on les demande) sauf lorsqu'une très grande portée est utilisée sur une machine privée de mémoire ou lorsque tous les éléments de la gamme ne sont jamais utilisés (comme lorsque la boucle est habituellement terminée avecbreak
).
C'est pour des raisons d'optimisation.
range () va créer 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 portées.
xrange () en revanche est beaucoup plus optimisé. il ne calcule la valeur suivante qu'en cas de besoin (via un objet xrange sequence) et ne crée pas de liste de toutes les valeurs comme range() does.
vous trouverez l'avantage de xrange
sur range
dans ce simple exemple:
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 bien meilleur dans le cas de xrange
.
regardez maintenant le cas suivant où range
est vraiment très lent, comparé à 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 (longue), mais xrange
est un générateur et ne génère des nombres basés que sur le besoin, c'est-à-dire si l'itération continue.
en Python-3, l'implémentation de la fonctionnalité range
est la même que celle de xrange
en Python-2, alors qu'ils ont supprimé xrange
en Python-3
Bon Codage!!
range (): range(1, 10) retourne une liste de 1 à 10 nombres et conserve la liste entière en mémoire.
xrange (): comme range(), mais au lieu de retourner une liste, retourne un objet qui génère les nombres dans la gamme à la demande. Pour la boucle, c'est légèrement plus rapide que range() et plus efficace en mémoire. xrange () produit les nombres sur demande.(Lazy Evaluation)
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
range(x,y)
retourne une liste de chaque nombre entre x et y si vous utilisez une boucle for
, alors range
est plus lent. En fait, range
a une plus grande fourchette D'indices. range(x.y)
va imprimer une liste de tous les numéros entre x et y
xrange(x,y)
retourne xrange(x,y)
mais si vous avez utilisé une boucle for
, alors xrange
est plus rapide. xrange
a une plus petite fourchette D'indices. xrange
n'imprimera pas seulement xrange(x,y)
mais il conservera tous les numéros qu'il contient.
[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 boucle for
, alors elle 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 des boucles, bien qu'il y ait une différence lors de l'impression!
en python 2.x
range(x) retourne une liste, qui est créée en mémoire avec des éléments X.
>>> 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 au cours de la boucle(Lazy Evaluation).
pour la boucle, c'est un peu plus rapide que la portée() et plus efficace en mémoire.
>>> b = xrange(5)
>>> b
xrange(5)
lors des essais de portée contre xrange dans une boucle (je sais que je devrais utiliser timeit , mais cela a été rapidement hacké de mémoire en utilisant un exemple simple de compréhension de liste) 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, à l'aide de 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
est-ce que mes tests sont corrects? Des commentaires sur l'instance plus lente de xrange? Ou un meilleur exemple :-)
certaines des autres réponses mentionnent que Python 3 a éliminé 2.x's range
et renommé 2.x xrange
à range
. Cependant, à moins que vous utilisiez 3.0 ou 3.1 (ce que personne ne devrait être), c'est en fait un type quelque peu différent.
Comme l'3.1 docs dis:
Les objets de portéeont très peu de comportement: ils ne supportent que l'indexation, l'itération et la fonction
len
.
Cependant, en 3.2+, range
est une séquence complète-il soutient tranches étendues, et toutes les méthodes de collections.abc.Sequence
avec la même sémantique que list
. *
et, au moins dans CPython et PyPy (les deux seules implémentations de 3.2+ qui existent actuellement), il a aussi des implémentations à temps constant des méthodes index
et count
et les in
." opérateur (aussi longtemps que vous le passer entiers). Cela signifie qu'écrire 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 issubclass(xrange, collections.Sequence)
renvoie True
en 2.6-2.7 et 3.0-3.1 est un bug qui a été corrigé en 3.2 et non rétroporté.
xrange() et range () en python fonctionnent de la même manière que pour l'utilisateur , mais la différence vient quand nous parlons de la façon dont la mémoire est allouée en utilisant à la fois la fonction.
lorsque nous utilisons range() nous affectons la mémoire pour toutes les variables qu'elle génère, il n'est donc pas recommandé d'utiliser avec plus grand no. de variables qui doivent être générés.
xrange() en revanche ne génère qu'une valeur particulière à un moment donné et ne peut être utilisé qu'avec la boucle for pour imprimer toutes les valeurs requises.
range génère la liste entière et la renvoie. xrange ne produit pas -- il génère les nombres dans la liste à la demande.
lire le post suivant pour la comparaison entre la gamme et xrange avec analyse graphique.
xrange utilise un itérateur (génère des valeurs à la volée), range renvoie une liste.
quoi?
range
renvoie une liste statique à l'exécution.
xrange
retourne un object
(qui agit comme un générateur, bien qu'il ne soit certainement pas un) à partir duquel les valeurs sont générées comme et quand requis.
quand utiliser lequel?
- utilisez
xrange
si vous voulez générer une liste pour une gamme gigantesque, disons 1 milliard, surtout quand vous avez une " mémoire sensible système" comme un téléphone cellulaire. - utilisez
range
si vous voulez itérer sur la liste plusieurs fois.
PS: Python 3.la fonction range
de x == Python 2.la fonction xrange
de x.
sur une exigence de numérisation/impression d'articles 0-N , gamme et xrange fonctionne comme suit.
range () - crée une nouvelle liste dans la mémoire et prend l'ensemble des éléments 0 à N (totalement N+1) et les imprime. xrange () - crée une instance itératrice qui scanne les éléments et garde seulement l'élément rencontré en cours dans la mémoire , utilisant ainsi la même quantité de mémoire tout le temps.
dans le cas où l'élément requis est quelque peu à la début de la liste seulement alors il sauve une bonne quantité de temps et de 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)
est seulement environ 20% plus efficace.
tout le monde l'a beaucoup expliqué. Mais je voulais voir par moi-même. J'utilise python3. Donc, j'ai ouvert le moniteur de ressources (dans Windows!), et d'abord exécuté la commande suivante en premier:
a=0
for i in range(1,100000):
a=a+i
, puis vérifié le changement dans la mémoire "en cours d'utilisation". C'était insignifiant. Puis, j'ai lancé 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'ai été convaincu. Vous pouvez l'essayer pour vous-même.
Si vous utilisez Python 2X, puis remplacer "range ()" par "xrange ()" dans le premier code et 'list(range())' avec 'range()'.
Range retourne une list tandis que xrange retourne un xrange objet qui prend la même mémoire indépendamment de la taille de la gamme,comme dans ce cas,un seul élément est généré et disponible par itération tandis que dans le cas d'utiliser la gamme, tous les éléments sont générés à la fois et sont disponibles dans la mémoire.
gamme: - la gamme peuplera tout à la fois.ce qui signifie que chaque nombre de la gamme occupera la mémoire.
xrange: - xrange est quelque chose comme générateur ,il viendra dans l'image quand vous voulez la gamme de nombres mais vous ne voulez pas qu'ils soient stockés,comme quand vous voulez utiliser pour boucle.donc la mémoire est efficace.
De l'aide docs.
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
renvoie une liste, xrange
renvoie un objet xrange qui est itérable.
En Python 3.x, range
devient xrange
de Python 2.x, et xrange
est supprimé.
voir ce post pour trouver la différence entre la gamme et xrange:
pour citer:
range
retourne exactement ce que vous pensez: une liste de entiers, d'une longueur définie commençant par 0.xrange
, cependant, renvoie un "objet xrange " , qui agit beaucoup comme un itérateur