460 votes

Faut-il toujours préférer xrange() à range() ?

Pourquoi ou pourquoi pas ?

36 votes

Quelqu'un peut-il décrire brièvement la différence entre les deux pour les personnes qui ne connaissent pasython ? Peut-être quelque chose comme "xrange() fait tout ce que range() fait, mais supporte aussi X, Y, et Z".

87 votes

Range(n) crée une liste contenant tous les entiers 0..n-1. C'est un problème si vous faites range(1000000), parce que vous vous retrouverez avec une liste de >4Mb. xrange s'occupe de cela en retournant un objet qui prétend être une liste, mais qui calcule juste le nombre nécessaire à partir de l'index demandé, et le retourne.

4 votes

446voto

Brian Points 48423

Pour des raisons de performance, surtout lorsque vous itérez sur une grande plage, xrange() est généralement meilleur. Toutefois, il existe encore quelques cas où vous pourriez préférer range() :

  • En python 3, range() fait ce qui suit xrange() qu'il avait l'habitude de faire et xrange() n'existe pas. Si vous voulez écrire du code qui fonctionnera à la fois sur Python 2 et Python 3, vous ne pouvez pas utiliser xrange() .

  • range() peut en fait être plus rapide dans certains cas - par exemple, si l'on itère sur la même séquence plusieurs fois. xrange() doit reconstruire l'objet entier à chaque fois, mais range() aura des objets entiers réels. (Cependant, les performances en termes de mémoire seront toujours moins bonnes).

  • xrange() n'est pas utilisable dans tous les cas où une vraie liste est nécessaire. Par exemple, il ne supporte pas les tranches, ni aucune méthode de liste.

[Il y a quelques messages qui mentionnent comment range() sera mis à jour par l'outil 2to3. Pour mémoire, voici le résultat de l'exécution de l'outil sur quelques exemples d'utilisations de range() y xrange()

RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: idioms
RefactoringTool: Skipping implicit fixer: ws_comma
--- range_test.py (original)
+++ range_test.py (refactored)
@@ -1,7 +1,7 @@

 for x in range(20):
-    a=range(20)
+    a=list(range(20))
     b=list(range(20))
     c=[x for x in range(20)]
     d=(x for x in range(20))
-    e=xrange(20)
+    e=range(20)

Comme vous pouvez le voir, lorsqu'il est utilisé dans une boucle for ou une compréhension, ou lorsqu'il est déjà enveloppé avec list(), range est laissé inchangé.

5 votes

Que voulez-vous dire par "l'intervalle deviendra un itérateur" ? Ne devrait-on pas plutôt dire "générateur" ?

4 votes

Non. Le générateur fait référence à un type spécifique d'itérateur, et la nouvelle fonction range n'est pas un itérateur de toute façon.

0 votes

Votre deuxième point n'a pas vraiment de sens. Vous dites que l'on ne peut pas utiliser un objet plusieurs fois ; bien sûr que l'on peut ! xr = xrange(1,11) puis sur la ligne suivante for i in xr: print " ".join(format(i*j,"3d") for j in xr) et voilà ! Vous avez vos tables de temps jusqu'à dix. Cela fonctionne de la même manière que r = range(1,11) y for i in r: print " ".join(format(i*j,"3d") for j in r) ... tout est un objet en Python2. Je pense que ce que vous vouliez dire, c'est que vous pouvez mieux faire de la compréhension basée sur l'index (si cela a un sens) avec range à l'opposé de xrange . La portée est très rare, je pense.

130voto

Dan Points 18831

Non, ils ont tous deux leur utilité :

Utilisez xrange() lors de l'itération, car cela permet d'économiser de la mémoire. Dites :

for x in xrange(1, one_zillion):

plutôt que :

for x in range(1, one_zillion):

D'autre part, utilisez range() si vous voulez réellement une liste de chiffres.

multiples_of_seven = range(7,100,7)
print "Multiples of seven < 100: ", multiples_of_seven

42voto

Thomas Wouters Points 38811

Vous devez privilégier range() sur xrange() uniquement lorsque vous avez besoin d'une liste réelle. Par exemple, lorsque vous voulez modifier la liste retournée par range() ou lorsque vous souhaitez le trancher. Pour l'itération ou même simplement l'indexation normale, xrange() fonctionnera parfaitement (et généralement de manière beaucoup plus efficace). Il y a un point où range() est un peu plus rapide que xrange() pour les très petites listes, mais en fonction de votre matériel et de divers autres détails, le seuil de rentabilité peut se situer à un résultat de longueur 1 ou 2 ; ce n'est pas quelque chose dont il faut s'inquiéter. Préférez xrange() .

31voto

Brian Minton Points 681

Une autre différence est que l'implémentation de Python 2 de la fonction xrange() ne supporte pas les nombres plus grands que les ints C, donc si vous voulez avoir une plage en utilisant le support intégré des grands nombres de Python, vous devez utiliser range() .

Python 2.7.3 (default, Jul 13 2012, 22:29:01) 
[GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> range(123456787676676767676676,123456787676676767676679)
[123456787676676767676676L, 123456787676676767676677L, 123456787676676767676678L]
>>> xrange(123456787676676767676676,123456787676676767676679)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: Python int too large to convert to C long

Python 3 n'a pas ce problème :

Python 3.2.3 (default, Jul 14 2012, 01:01:48) 
[GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> range(123456787676676767676676,123456787676676767676679)
range(123456787676676767676676, 123456787676676767676679)

13voto

Dan Udey Points 1994

xrange() est plus efficace car au lieu de générer une liste d'objets, elle ne génère qu'un seul objet à la fois. Au lieu d'avoir 100 entiers, et tous leurs frais généraux, et la liste dans laquelle les placer, vous avez juste un entier à la fois. Génération plus rapide, meilleure utilisation de la mémoire, code plus efficace.

À moins que j'aie besoin d'une liste pour quelque chose en particulier, je privilégie toujours xrange()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X