Pourquoi ou pourquoi pas ?
Que voulez-vous dire par "l'intervalle deviendra un itérateur" ? Ne devrait-on pas plutôt dire "générateur" ?
Pourquoi ou pourquoi pas ?
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é.
Que voulez-vous dire par "l'intervalle deviendra un itérateur" ? Ne devrait-on pas plutôt dire "générateur" ?
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.
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.
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
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()
.
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)
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 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.
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
Voir stackoverflow.com/questions/94935
4 votes
Fondamentalement, alors que
range(1000)
est unlist
,xrange(1000)
est un objet qui agit comme ungenerator
(bien que ce soit certainement no un). Aussi,xrange
est plus rapide. Vous pouvezimport timeit from timeit
et ensuite faire une méthode qui a justefor i in xrange: pass
et un autre pourrange
alors, faitestimeit(method1)
ytimeit(method2)
et, ô surprise, xrange est parfois presque deux fois plus rapide (c'est-à-dire lorsque vous n'avez pas besoin de liste). (Pour moi, pouri in xrange(1000):pass
vs pouri in range(1000):pass
a pris13.316725969314575
vs21.190124988555908
secondes respectivement - c'est beaucoup).0 votes
Un autre test de performance donne
xrange(100)
20 % plus rapide querange(100)
.