Alguém pode descrever brevemente a diferença entre os 2 para nós, não-python? Talvez algo como "xrange () não Everyhing range () faz, mas também suporta X, Y e Z"
Outlaw Programmer
87
range (n) cria uma lista contendo todos os números inteiros 0..n-1. Este é um problema se você atingir o intervalo (1000000), porque você terminará com uma lista> 4Mb. O xrange lida com isso retornando um objeto que finge ser uma lista, mas apenas calcula o número necessário no índice solicitado e retorna isso.
Basicamente, enquanto que range(1000)é a list, xrange(1000)é um objeto que age como um generator(embora certamente não seja um). Além disso, xrangeé mais rápido. Você pode import timeit from timeite, em seguida, fazer um método que só tem for i in xrange: passe outro para range, em seguida, fazer timeit(method1)e timeit(method2)e, vejam só, xrange é quase duas vezes mais rápido às vezes (que é quando você não precisa de uma lista). (Para mim, para i in xrange(1000):passvs para i in range(1000):passlevou 13.316725969314575vs 21.190124988555908segundos, respectivamente - que é um monte.)
Para o desempenho, especialmente quando você está interagindo em uma grande variedade, xrange()geralmente é melhor. No entanto, ainda existem alguns casos pelos quais você pode preferir range():
No python 3, range()faz o que xrange()costumava fazer e xrange()não existe. Se você deseja escrever um código que será executado no Python 2 e no Python 3, não poderá usá-lo xrange().
range()pode realmente ser mais rápido em alguns casos - por exemplo. se iterando na mesma sequência várias vezes. xrange()precisa reconstruir o objeto inteiro toda vez, mas range()terá objetos inteiros reais. (No entanto, sempre terá um desempenho pior em termos de memória)
xrange()não é utilizável em todos os casos em que é necessária uma lista real. Por exemplo, ele não suporta fatias ou qualquer método de lista.
[Editar] Existem algumas postagens mencionando como range()será atualizado pela ferramenta 2to3. Para o registro, aqui está o resultado da execução da ferramenta em alguns exemplos de usos range()exrange()
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)
Como você pode ver, quando usado em um loop ou compreensão for, ou onde já está envolvido com list (), o intervalo permanece inalterado.
O que você quer dizer com "intervalo se tornará um iterador"? Isso não deveria ser "gerador"?
Michael Mior
4
Não. O gerador se refere a um tipo específico de iterador, e o novo rangenão é um iterador de qualquer maneira.
User2357112 suporta Monica
Sua segunda bala não faz muito sentido. Você está dizendo que não pode usar um objeto várias vezes; Certamente você pode! tente xr = xrange(1,11)então na próxima linha for i in xr: print " ".join(format(i*j,"3d") for j in xr)e pronto! Você tem seus horários até dez. Funciona da mesma forma que r = range(1,11)e for i in r: print " ".join(format(i*j,"3d") for j in r)... tudo é um objeto no Python2. Eu acho que o que você quis dizer é que você pode fazer melhor a compreensão baseada em índice (se isso faz sentido) melhor do rangeque o contrário xrange. Faixa é útil muito raramente, eu acho
dylnmc
(Quarto não suficiente) Embora, eu faço pensar que rangepode ser útil se você quiser usar um listem um loop e, em seguida, mudar certos índices baseados em certas condições ou coisas anexar a essa lista, então rangeé definitivamente melhor. No entanto, xrangeé simplesmente mais rápido e utiliza menos memória; portanto, para a maioria dos aplicativos de loop for, parece ser o melhor. Há casos - voltando à pergunta do interlocutor - raramente, mas existentes, onde rangeseria melhor. Talvez não tão raramente quanto estou pensando, mas certamente uso xrange95% do tempo.
dylnmc
129
Não, ambos têm seus usos:
Use xrange()ao iterar, pois economiza memória. Dizer:
for x in xrange(1, one_zillion):
ao invés de:
for x in range(1, one_zillion):
Por outro lado, use range()se você realmente deseja uma lista de números.
multiples_of_seven = range(7,100,7)print"Multiples of seven < 100: ", multiples_of_seven
Você deve favorecer range()mais xrange()somente quando você precisa de uma lista real. Por exemplo, quando você deseja modificar a lista retornada por range()ou quando deseja cortá-la. Para iteração ou até apenas indexação normal, xrange()funcionará bem (e geralmente com muito mais eficiência). Há um ponto em que range()é um pouco mais rápido do que xrange()para listas muito pequenas, mas, dependendo do seu hardware e de vários outros detalhes, o ponto de equilíbrio pode ser o resultado do comprimento 1 ou 2; não é algo para se preocupar. Preferir xrange().
Uma outra diferença é que xrange () não pode suportar números maiores que C ints; portanto, se você deseja ter um intervalo usando o suporte de grande número incorporado do python, você deve usar range ().
Python2.7.3(default,Jul132012,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ão tem esse problema:
Python3.2.3(default,Jul142012,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()é mais eficiente porque, em vez de gerar uma lista de objetos, apenas gera um objeto por vez. Em vez de 100 números inteiros, toda a sobrecarga e a lista para inseri-los, você apenas tem um número inteiro por vez. Geração mais rápida, melhor uso da memória, código mais eficiente.
A menos que eu precise especificamente de uma lista para alguma coisa, eu sempre a favor xrange()
range () retorna uma lista, xrange () retorna um objeto xrange.
xrange () é um pouco mais rápido e um pouco mais eficiente em termos de memória. Mas o ganho não é muito grande.
Obviamente, a memória extra usada por uma lista não é desperdiçada, as listas têm mais funcionalidades (cortar, repetir, inserir, ...). As diferenças exatas podem ser encontradas na documentação . Não há regra rígida, use o que for necessário.
O Python 3.0 ainda está em desenvolvimento, mas o intervalo IIRC () será muito semelhante ao xrange () de 2.X e list (range ()) pode ser usado para gerar listas.
Gostaria apenas de dizer que REALMENTE não é tão difícil obter um objeto xrange com funcionalidade de fatia e indexação. Eu escrevi um código que funciona muito bem e é tão rápido quanto o xrange para quando conta (iterações).
from __future__ import division
def read_xrange(xrange_object):# returns the xrange object's start, stop, and step
start = xrange_object[0]if len(xrange_object)>1:
step = xrange_object[1]- xrange_object[0]else:
step =1
stop = xrange_object[-1]+ step
return start, stop, step
classXrange(object):''' creates an xrange-like object that supports slicing and indexing.
ex: a = Xrange(20)
a.index(10)
will work
Also a[:5]
will return another Xrange object with the specified attributes
Also allows for the conversion from an existing xrange object
'''def __init__(self,*inputs):# allow inputs of xrange objectsif len(inputs)==1:
test,= inputs
if type(test)== xrange:
self.xrange = test
self.start, self.stop, self.step = read_xrange(test)return# or create one from start, stop, step
self.start, self.step =0,Noneif len(inputs)==1:
self.stop,= inputs
elif len(inputs)==2:
self.start, self.stop = inputs
elif len(inputs)==3:
self.start, self.stop, self.step = inputs
else:raiseValueError(inputs)
self.xrange = xrange(self.start, self.stop, self.step)def __iter__(self):return iter(self.xrange)def __getitem__(self, item):if type(item)is int:if item <0:
item += len(self)return self.xrange[item]if type(item)is slice:# get the indexes, and then convert to the number
start, stop, step = item.start, item.stop, item.step
start = start if start !=Noneelse0# convert start = None to start = 0if start <0:
start += start
start = self[start]if start <0:raiseIndexError(item)
step =(self.step if self.step !=Noneelse1)*(step if step !=Noneelse1)
stop = stop if stop isnotNoneelse self.xrange[-1]if stop <0:
stop += stop
stop = self[stop]
stop = stop
if stop > self.stop:raiseIndexErrorif start < self.start:raiseIndexErrorreturnXrange(start, stop, step)def index(self, value):
error =ValueError('object.index({0}): {0} not in object'.format(value))
index =(value - self.start)/self.step
if index %1!=0:raise error
index = int(index)try:
self.xrange[index]except(IndexError,TypeError):raise error
return index
def __len__(self):return len(self.xrange)
Honestamente, acho que a questão toda é meio boba e o xrange deve fazer tudo isso de qualquer maneira ...
Sim concordou; de uma tecnologia totalmente diferente, verifique o trabalho no lodash para torná-lo preguiçoso: github.com/lodash/lodash/issues/274 . Fatiar, etc, ainda deve ser o mais preguiçoso possível e, onde não, só então reificar.
Rob Grant
4
Um bom exemplo dado no livro: Python Prático Por Magnus Lie Hetland
Eu não recomendaria usar o intervalo em vez de xrange no exemplo anterior - embora apenas os cinco primeiros números sejam necessários, o intervalo calcula todos os números e isso pode levar muito tempo. Com o xrange, isso não é um problema, pois calcula apenas os números necessários.
Sim, eu li a resposta do @ Brian: No python 3, range () é um gerador de qualquer maneira e xrange () não existe.
Não faça isso. O xrange () desaparecerá, mas muitas outras coisas também. A ferramenta que você usará para traduzir seu código Python 2.x para o código Python 3.x converterá automaticamente xrange () para range (), mas range () será traduzido para a lista menos eficiente (range ()).
Thomas Wouters
10
Thomas: Na verdade, é um pouco mais inteligente que isso. Ele converterá range () em situações em que claramente não precisa de uma lista real (por exemplo, em um loop for ou compreensão) em apenas range (). Somente casos em que é atribuído a uma variável, ou usados diretamente devem ser acondicionadas com list ()
Brian
2
Ok, todos aqui têm uma opinião diferente sobre as vantagens e desvantagens de xrange versus range. Eles estão na maioria corretos, o xrange é um iterador, e o intervalo é atualizado e cria uma lista real. Na maioria dos casos, você realmente não notará diferença entre os dois. (Você pode usar o mapa com alcance, mas não com xrange, mas ele consome mais memória.)
O que eu acho que você quer ouvir, no entanto, é que a escolha preferida é o intervalo. Como o range no Python 3 é um iterador, a ferramenta de conversão de código 2to3 converterá corretamente todos os usos do xrange em range e emitirá um erro ou aviso para o uso do range. Se você deseja converter facilmente seu código no futuro, usará apenas xrange e listará (xrange) quando tiver certeza de que deseja uma lista. Aprendi isso durante o CPython sprint na PyCon este ano (2008) em Chicago.
Isso não é verdade. Código como "para x no intervalo (20)" será deixado como intervalo e código como "x = intervalo (20)" será convertido em "x = lista (intervalo (20))" - sem erros. Além disso, se você deseja escrever um código que será executado tanto em 2.6 quanto em 3.0, range () é sua única opção sem adicionar funções de compatibilidade.
Brian
2
range(): range(1, 10)retorna uma lista de 1 a 10 números e mantém a lista inteira na memória.
xrange(): Como range(), mas em vez de retornar uma lista, retorna um objeto que gera os números no intervalo sob demanda. Para loop, isso é levemente mais rápido range()e mais eficiente em memória. xrange()objeto como um iterador e gera os números sob demanda (Lazy Evaluation).
range()faz o mesmo que xrange()costumava fazer no Python 3 e não xrange()existe um termo no Python 3.
range()Na verdade, pode ser mais rápido em alguns cenários se você estiver repetindo a mesma sequência várias vezes. xrange()precisa reconstruir o objeto inteiro toda vez, mas range()terá objetos inteiros reais.
Embora xrangeseja mais rápido do que rangena maioria das circunstâncias, a diferença de desempenho é bastante mínima. O pequeno programa abaixo compara a iteração sobre a rangee an xrange:
import timeit
# Try various list sizes.for list_len in[1,10,100,1000,10000,100000,1000000]:# Time doing a range and an xrange.
rtime = timeit.timeit('a=0;\nfor n in range(%d): a += n'%list_len, number=1000)
xrtime = timeit.timeit('a=0;\nfor n in xrange(%d): a += n'%list_len, number=1000)# Print the resultprint"Loop list of len %d: range=%.4f, xrange=%.4f"%(list_len, rtime, xrtime)
Os resultados abaixo mostram que xrangeé realmente mais rápido, mas não o suficiente para transpirar.
Loop list of len 1: range=0.0003, xrange=0.0003Loop list of len 10: range=0.0013, xrange=0.0011Loop list of len 100: range=0.0068, xrange=0.0034Loop list of len 1000: range=0.0609, xrange=0.0438Loop list of len 10000: range=0.5527, xrange=0.5266Loop list of len 100000: range=10.1666, xrange=7.8481Loop list of len 1000000: range=168.3425, xrange=155.8719
Portanto, use todos os meios xrange, mas a menos que você esteja usando um hardware restrito, não se preocupe muito com isso.
range(1000)
é alist
,xrange(1000)
é um objeto que age como umgenerator
(embora certamente não seja um). Além disso,xrange
é mais rápido. Você podeimport timeit from timeit
e, em seguida, fazer um método que só temfor i in xrange: pass
e outro pararange
, em seguida, fazertimeit(method1)
etimeit(method2)
e, vejam só, xrange é quase duas vezes mais rápido às vezes (que é quando você não precisa de uma lista). (Para mim, parai in xrange(1000):pass
vs parai in range(1000):pass
levou13.316725969314575
vs21.190124988555908
segundos, respectivamente - que é um monte.)xrange(100)
20% mais rápido querange(100)
.Respostas:
Para o desempenho, especialmente quando você está interagindo em uma grande variedade,
xrange()
geralmente é melhor. No entanto, ainda existem alguns casos pelos quais você pode preferirrange()
:No python 3,
range()
faz o quexrange()
costumava fazer exrange()
não existe. Se você deseja escrever um código que será executado no Python 2 e no Python 3, não poderá usá-loxrange()
.range()
pode realmente ser mais rápido em alguns casos - por exemplo. se iterando na mesma sequência várias vezes.xrange()
precisa reconstruir o objeto inteiro toda vez, masrange()
terá objetos inteiros reais. (No entanto, sempre terá um desempenho pior em termos de memória)xrange()
não é utilizável em todos os casos em que é necessária uma lista real. Por exemplo, ele não suporta fatias ou qualquer método de lista.[Editar] Existem algumas postagens mencionando como
range()
será atualizado pela ferramenta 2to3. Para o registro, aqui está o resultado da execução da ferramenta em alguns exemplos de usosrange()
exrange()
Como você pode ver, quando usado em um loop ou compreensão for, ou onde já está envolvido com list (), o intervalo permanece inalterado.
fonte
range
não é um iterador de qualquer maneira.xr = xrange(1,11)
então na próxima linhafor i in xr: print " ".join(format(i*j,"3d") for j in xr)
e pronto! Você tem seus horários até dez. Funciona da mesma forma quer = range(1,11)
efor i in r: print " ".join(format(i*j,"3d") for j in r)
... tudo é um objeto no Python2. Eu acho que o que você quis dizer é que você pode fazer melhor a compreensão baseada em índice (se isso faz sentido) melhor dorange
que o contrárioxrange
. Faixa é útil muito raramente, eu achorange
pode ser útil se você quiser usar umlist
em um loop e, em seguida, mudar certos índices baseados em certas condições ou coisas anexar a essa lista, entãorange
é definitivamente melhor. No entanto,xrange
é simplesmente mais rápido e utiliza menos memória; portanto, para a maioria dos aplicativos de loop for, parece ser o melhor. Há casos - voltando à pergunta do interlocutor - raramente, mas existentes, onderange
seria melhor. Talvez não tão raramente quanto estou pensando, mas certamente usoxrange
95% do tempo.Não, ambos têm seus usos:
Use
xrange()
ao iterar, pois economiza memória. Dizer:ao invés de:
Por outro lado, use
range()
se você realmente deseja uma lista de números.fonte
Você deve favorecer
range()
maisxrange()
somente quando você precisa de uma lista real. Por exemplo, quando você deseja modificar a lista retornada porrange()
ou quando deseja cortá-la. Para iteração ou até apenas indexação normal,xrange()
funcionará bem (e geralmente com muito mais eficiência). Há um ponto em querange()
é um pouco mais rápido do quexrange()
para listas muito pequenas, mas, dependendo do seu hardware e de vários outros detalhes, o ponto de equilíbrio pode ser o resultado do comprimento 1 ou 2; não é algo para se preocupar. Preferirxrange()
.fonte
Uma outra diferença é que xrange () não pode suportar números maiores que C ints; portanto, se você deseja ter um intervalo usando o suporte de grande número incorporado do python, você deve usar range ().
Python 3 não tem esse problema:
fonte
xrange()
é mais eficiente porque, em vez de gerar uma lista de objetos, apenas gera um objeto por vez. Em vez de 100 números inteiros, toda a sobrecarga e a lista para inseri-los, você apenas tem um número inteiro por vez. Geração mais rápida, melhor uso da memória, código mais eficiente.A menos que eu precise especificamente de uma lista para alguma coisa, eu sempre a favor
xrange()
fonte
range () retorna uma lista, xrange () retorna um objeto xrange.
xrange () é um pouco mais rápido e um pouco mais eficiente em termos de memória. Mas o ganho não é muito grande.
Obviamente, a memória extra usada por uma lista não é desperdiçada, as listas têm mais funcionalidades (cortar, repetir, inserir, ...). As diferenças exatas podem ser encontradas na documentação . Não há regra rígida, use o que for necessário.
O Python 3.0 ainda está em desenvolvimento, mas o intervalo IIRC () será muito semelhante ao xrange () de 2.X e list (range ()) pode ser usado para gerar listas.
fonte
Gostaria apenas de dizer que REALMENTE não é tão difícil obter um objeto xrange com funcionalidade de fatia e indexação. Eu escrevi um código que funciona muito bem e é tão rápido quanto o xrange para quando conta (iterações).
Honestamente, acho que a questão toda é meio boba e o xrange deve fazer tudo isso de qualquer maneira ...
fonte
Um bom exemplo dado no livro: Python Prático Por Magnus Lie Hetland
Eu não recomendaria usar o intervalo em vez de xrange no exemplo anterior - embora apenas os cinco primeiros números sejam necessários, o intervalo calcula todos os números e isso pode levar muito tempo. Com o xrange, isso não é um problema, pois calcula apenas os números necessários.
Sim, eu li a resposta do @ Brian: No python 3, range () é um gerador de qualquer maneira e xrange () não existe.
fonte
Vá com alcance por estes motivos:
1) O xrange desaparecerá nas versões mais recentes do Python. Isso oferece fácil compatibilidade futura.
2) o alcance assumirá as eficiências associadas ao xrange.
fonte
Ok, todos aqui têm uma opinião diferente sobre as vantagens e desvantagens de xrange versus range. Eles estão na maioria corretos, o xrange é um iterador, e o intervalo é atualizado e cria uma lista real. Na maioria dos casos, você realmente não notará diferença entre os dois. (Você pode usar o mapa com alcance, mas não com xrange, mas ele consome mais memória.)
O que eu acho que você quer ouvir, no entanto, é que a escolha preferida é o intervalo. Como o range no Python 3 é um iterador, a ferramenta de conversão de código 2to3 converterá corretamente todos os usos do xrange em range e emitirá um erro ou aviso para o uso do range. Se você deseja converter facilmente seu código no futuro, usará apenas xrange e listará (xrange) quando tiver certeza de que deseja uma lista. Aprendi isso durante o CPython sprint na PyCon este ano (2008) em Chicago.
fonte
range()
:range(1, 10)
retorna uma lista de 1 a 10 números e mantém a lista inteira na memória.xrange()
: Comorange()
, mas em vez de retornar uma lista, retorna um objeto que gera os números no intervalo sob demanda. Para loop, isso é levemente mais rápidorange()
e mais eficiente em memória.xrange()
objeto como um iterador e gera os números sob demanda (Lazy Evaluation).range()
faz o mesmo quexrange()
costumava fazer no Python 3 e nãoxrange()
existe um termo no Python 3.range()
Na verdade, pode ser mais rápido em alguns cenários se você estiver repetindo a mesma sequência várias vezes.xrange()
precisa reconstruir o objeto inteiro toda vez, masrange()
terá objetos inteiros reais.fonte
Embora
xrange
seja mais rápido do querange
na maioria das circunstâncias, a diferença de desempenho é bastante mínima. O pequeno programa abaixo compara a iteração sobre arange
e anxrange
:Os resultados abaixo mostram que
xrange
é realmente mais rápido, mas não o suficiente para transpirar.Portanto, use todos os meios
xrange
, mas a menos que você esteja usando um hardware restrito, não se preocupe muito com isso.fonte
list_len
não está sendo usado e assim você só está executando este código para listas de comprimento 100.rtime = timeit.timeit('a=0;\nfor n in range(%d): a += n' % list_len, number=1000)