range() vs xrange()

(válido somente para Python 2.x)

A função range()

Em Python, é muito comum usarmos a seguinte estrutura para realizar uma repetição baseada em um contador:

for i in range(0, 10):
    print i,

A função range(x, y) gera uma lista de números inteiros de x até y (sem incluir o segundo). Assim, range(0, 10), gera a seguinte lista:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Desse modo, a variável i é iterada sobre essa lista, através da estrutura de repetição for. O trecho de código:

for i in range(0, 10):
    print i,

pode ser lido como:

"Para cada elemento na lista [0,1,2,3,4,5,6,7,8,9], imprima tal elemento"

Usar range() ou xrange()? Eis a questão…

É comum ouvirmos ou lermos algum desenvolvedor Python aconselhando a utilização da função xrange() ao invés da função range(), por questões de desempenho. Mas o que é essa tal de xrange()?

A xrange() nada mais é do que uma função que pode, em muitos casos (não sempre), substituir o uso da função range(), fornecendo ainda melhor desempenho. Veja o código abaixo:

for i in xrange(0, 10):
    print i,

O resultado dessa execução é o mesmo de quando utilizamos a função range(), porém, por gerar um elemento de cada vez, o código que utiliza a função xrange() apresenta um desempenho superior.

Quando executamos:

for i in range(0, 1000000000):
    pass

A função range() irá imediatamente gerar uma lista contendo um bilhão de inteiros e alocar essa lista na memória. Uma lista contendo um bilhão de inteiros é capaz de encher a memória de um computador pessoal.

Já com a função xrange(), ao executarmos:

for i in xrange(0, 1000000000):
    pass

Cada um dos inteiros (dos 1 bilhão) será gerado de uma vez, economizando memória e tempo de startup.

Vamos então testar o desempenho usando o módulo timeit().

 

A hora da verdade

junior@qwerty:~ $ python -m timeit "for i in xrange(10000000): pass"
 10 loops, best of 3: 246 msec per loop
junior@qwerty:~-$ python -m timeit "for i in range(10000000): pass"
 10 loops, best of 3: 342 msec per loop

Como podemos ver, o loop que utiliza a função xrange() foi quase 100 milisegundos mais rápido do que o loop que utiliza a função range(). Além disso, se fizermos uma análise de consumo de memória, veremos que a o código que utiliza a função range() utiliza uma quantidade de memória muito maior, pois gera a lista inteira antes de executar a iteração do for.

Então nunca mais vou usar o range(), certo?

Errado! Existe uma diferença fundamental entre as duas funções: a função xrange() não gera uma lista. Isso torna inviável, por exemplo, o slicing e a gravação de seu resultado como uma lista em uma variável. Vejamos:

>>> x = range(0, 10)
>>> print x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> y = xrange(0, 10)
>>> print y
xrange(10)

Ou seja, apesar de nos fornecer um desempenho superior ao desempenho obtido com a range(), a função xrange() não substitui a anterior em todos os seus casos.

7 comentários sobre “range() vs xrange()

  1. meu amigo, me desculpe mas eu tenho que discordar! , no ultimo caso que você disse que xrange() não substitui range() , posso substitui-lo como no exempo:

    s = list(xrange(10))

    então “print s” resultaria em:

    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    • Poder até pode, assim como você poderia criar um objeto inteiro da seguinte forma:

      >>> x = int(float(str(float(1))))
      

      😛

      Por que converter um objeto xrange em uma lista se eu posso obter uma lista usando o range direto?

      Valeu pelo comentário!

  2. Pingback: O que mudou no Python 3? | Python Help

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s