it-swarm-eu.dev

Jaký je rozdíl mezi funkcemi rozsahu a xrange v Pythonu 2.X?

Zdá se, že xrange je rychlejší, ale nemám ponětí, proč je to rychlejší (a bez důkazu kromě toho, že je rychlejší), nebo co je jinak odlišné

for i in range(0, 20):
for i in xrange(0, 20):
644
Teifion

range vytvoří seznam, takže pokud uděláte range(1, 10000000), vytvoří se v paměti seznam s 9999999 elementy.

xrange je objekt posloupnosti, který hodnotí jenivě. 

Mělo by to být přidáno z nápovědy @ Thiago, že v python3 rozsah odpovídá ekvivalentu pyranu xrange 

735
Charles

range vytvoří seznam, takže pokud uděláte range(1, 10000000), vytvoří se v paměti seznam s 9999999 prvky.

xrange je generátor, takže je objekt sekvence je , který hodnotí jenivě. 

Toto je pravda, ale v Pythonu 3 bude .range() implementován Python 2 .xrange(). Pokud potřebujete seznam skutečně vygenerovat, musíte provést následující kroky:

list(range(1,100))
215
Corey

Nezapomeňte použít modul timeit k testování toho, který malý úryvek kódu je rychlejší!

$ 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

Osobně vždy používám .range(), ledaže jsem se zabýval opravdu obrovskými seznamy - jak vidíte, čas od času, pro seznam miliónů záznamů, extra režie je pouze 0,04 sekundy. A jak poukazuje Corey, v Pythonu 3.0 .xrange() zmizí a .range() vám stejně udělá hezké iterátorové chování.

103
John Fouhy

xrange ukládá pouze parametry rozsahu a generuje čísla na vyžádání. Implementace C jazyka Python však v současné době omezuje jeho args na 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]

Všimněte si, že v Pythonu 3.0 existuje pouze range a chová se jako 2.xxrange, ale bez omezení minimálních a maximálních koncových bodů.

64
efotinis

xrange vrací iterátor a udržuje pouze jedno číslo v paměti. rozsah uchovává celý seznam čísel v paměti.

38
Ben Hoffstein

Udělejte si nějaký čas s Referencí knihovny . Čím znáte, tím rychleji můžete najít odpovědi na takové otázky. Zvláště důležité jsou první kapitoly o zabudovaných objektech a typech.

Výhodou typu xrange je, že objekt xrange bude vždy Mít stejnou velikost paměti, bez ohledu na velikost rozsahu, který představuje. Neexistují žádné konzistentní výhody výkonu.

Dalším způsobem, jak najít rychlé informace o konstruktu Python, je docstring a pomocná funkce:

print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
28
Antti Rasinen

Jsem šokován nikdo nečetl doc :

Tato funkce je velmi podobná funkci range(), ale místo seznamu vrací objekt xrange. Jedná se o neprůhledný typ sekvence, který poskytuje stejné hodnoty jako odpovídající seznam, aniž by je skutečně všechny současně ukládal. Výhoda xrange() over range() je minimální (protože xrange() stále musí vytvářet hodnoty, když je o to požádán), s výjimkou případů, kdy je na stroji s hladověním paměťovým systémem používán velmi velký rozsah, nebo když nejsou nikdy použity všechny prvky rozsahu (např. Když smyčka je obvykle ukončena break).

13
Kishor Pawar

rozsah vytvoří seznam, takže pokud uděláte rozsah (1, 10000000), vytvoří se v paměti seznam s 10000000 prvky. xrange je generátor, takže hodnotí jenivě.

To přináší dvě výhody:

  1. Delší seznamy můžete iterovat bez získání MemoryError.
  2. Jak to vyřeší každé číslo jenivě, pokud zastavíte iteraci brzy, nebudete ztrácet čas vytvářením celého seznamu.
12
Lucas S.

Je to z důvodů optimalizace.

range () vytvoří seznam hodnot od začátku do konce (ve vašem příkladu 0 .. 20). To se stane nákladným provozem na velmi velkém rozsahu.

xrange () na druhé straně je mnohem optimalizovanější. další hodnotu vypočítá pouze v případě potřeby (přes objekt sekvence xrange) a nevytvoří seznam všech hodnot, jako je rozsah ().

10
QAZ

V tomto jednoduchém příkladu najdete výhodu xrange nad range:

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

Výše uvedený příklad neodráží nic podstatně lepšího v případě xrange.

Nyní se podívejte na následující případ, kdy range je opravdu pomalé ve srovnání s 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

S range již vytváří seznam od 0 do 100000000 (časově náročné), ale xrange je generátor a generuje pouze čísla na základě potřeby, tj. Pokud iterace pokračuje.

V Pythonu-3 je implementace funkce range stejná jako u xrange v Pythonu-2, zatímco s xrange v Pythonu-3 byly odstraněny.

Happy Coding !! 

10
User_Targaryen

range (): range (1, 10) vrátí seznam od 1 do 10 čísel a podrží celý seznam v paměti.

xrange (): Like range (), ale místo vrácení seznamu vrátí objekt, který generuje čísla v rozsahu na vyžádání. Pro smyčkování je to lehce rychlejší než rozsah () a efektivnější paměti. Xrange () objekt jako iterátor a generuje čísla na vyžádání (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
8
Tushar.PUCSD

range(x,y) vrátí seznam každého čísla mezi x a y, pokud použijete smyčku for, pak range je pomalejší. range má ve skutečnosti větší rozsah indexů. range(x.y) vytiskne seznam všech čísel mezi x a y

xrange(x,y) vrací xrange(x,y), ale pokud jste použili smyčku for, pak xrange je rychlejší. xrange má menší rozsah indexů. xrange bude nejen tisknout xrange(x,y), ale bude stále uchovávat všechna čísla, která jsou v něm.

[In] range(1,10)
[Out] [1, 2, 3, 4, 5, 6, 7, 8, 9]
[In] xrange(1,10)
[Out] xrange(1,10)

Pokud použijete smyčku for, pak to bude fungovat

[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

Není tam žádný rozdíl, když používáte smyčky, i když je rozdíl, když právě tisk!

8
Supercolbat

V pythonu 2.x.

range (x) vrátí seznam, který je vytvořen v paměti pomocí x prvků.

>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]

xrange (x) vrátí objekt xrange, který je generátorem, který generuje čísla na vyžádání. jsou počítány během smyčky (Lazy Evaluation).

Pro smyčky je to o něco rychlejší než rozsah () a více paměti.

>>> b = xrange(5)
>>> b
xrange(5)
6
SrmHitter9062

Když testujete rozsah proti xrange ve smyčce (vím, že bych měl použít timeit , ale to bylo rychle hacknut z paměti pomocí jednoduchého seznamu příklad porozumění) Našel jsem následující:

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)

který dává:

$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?

Nebo pomocí xrange ve smyčce 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

Je moje útržkovité testování správně? Jakékoliv komentáře k pomalejší instanci xrange? Nebo lepší příklad :-)

5
Dave Everitt

Některé z dalších odpovědí uvádějí, že Python 3 eliminoval range_x a přejmenoval 2.xxrange na range. Pokud však nepoužíváte 3.0 nebo 3.1 (což by nikdo neměl být), je to vlastně poněkud jiný typ.

Jak 3,1 docs řekněme:

Objekty rozsahu mají velmi malé chování: podporují pouze indexování, iteraci a funkci len.

Ve verzi 3.2+ je však range úplná posloupnost - podporuje rozšířené řezy a všechny metody collections.abc.Sequence se stejnou sémantikou jako list.*

A přinejmenším v CPythonu a PyPy (pouze dvě implementace 3.2+, které v současné době existují), má také konstantní implementace metod index a count a operátoru in (pokud jen projdete celá čísla). To znamená, že zápis 123456 in r je rozumný v 3.2+, zatímco v 2.7 nebo 3.1 by to byl hrozný nápad.


* Skutečnost, že issubclass(xrange, collections.Sequence) vrací True v 2.6-2.7 a 3.0-3.1 je chyba která byla opravena v 3.2 a nebyla backportována.

5
abarnert

xrange () a range () v pythonu funguje podobně jako u uživatele, ale rozdíl přichází, když hovoříme o tom, jak je paměť přidělena při použití funkce.

Když používáme range (), přidělujeme paměť pro všechny proměnné, které generuje, takže se nedoporučuje používat s větším číslem. generovaných proměnných.

xrange () na druhé straně generuje pouze určitou hodnotu najednou a lze ji použít pouze se smyčkou for pro tisk všech požadovaných hodnot.

4

Přečtěte si následující příspěvek pro porovnání rozsahu a xrange s grafickou analýzou.

Pyranový rozsah Vs xrange

3
Harsha Vardhan

generuje celý seznam a vrací jej. xrange ne - generuje čísla v seznamu na vyžádání.

3
Eddie Deyo

Co?
range vrací runtime statický seznam.
xrange vrací object (který funguje jako generátor, i když to rozhodně není jeden), ze kterého jsou hodnoty generovány podle potřeby.

Kdy použít který? 

  • Použijte xrange, pokud chcete vytvořit seznam pro gigantický rozsah, řekněme 1 miliardu, zvláště když máte "systém citlivý na paměť" jako mobilní telefon.
  • Použijte range, pokud chcete několikrát iterovat seznam.

PS: Python 3.x je range funkce == Python 2.x je xrange funkce.

2
kmario23

xrange používá iterátor (generuje hodnoty za běhu), rozsah vrací seznam.

2
hacama

Rozdíl menší pro menší argumenty na 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

V tomto případě je xrange(100) pouze o 20% efektivnější.

1
Evgeni Sergeev

Na požadavku na skenování/tisk položek 0-N funguje rozsah a xrange následovně.

range () - vytvoří nový seznam v paměti a vezme celé položky 0 až N (zcela N + 1) a vytiskne je. xrange () - vytvoří instanci iterátoru, která prohledává položky a udržuje pouze aktuální položka se nacházela v paměti, a proto po celou dobu využívá stejné množství paměti.

V případě, že požadovaný prvek je poněkud na začátku seznamu, pak ušetří spoustu času a paměti.

1
SomeDoubts

Každý to velmi vysvětlil. Ale chtěla jsem, aby to viděla sama pro sebe. Používám python3. Otevřel jsem tedy monitor zdrojů (v systému Windows!) A nejprve provedl následující příkaz:

a=0
for i in range(1,100000):
    a=a+i

a poté zkontrolovat změnu v paměti 'In Use'. Bylo to bezvýznamné. Pak jsem provedl následující kód:

for i in list(range(1,100000)):
    a=a+i

Okamžitě to trvalo velké množství paměti. Byl jsem přesvědčen. Můžete to vyzkoušet sami.

Pokud používáte Python 2X, nahraďte 'range ()' s 'xrange ()' v prvním kódu a 'list (range ())' s 'range ()'.

1
ANKUR SATYA

Z dokumentace nápovědy.

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

Rozdíl je zřejmý. V Pythonu 2.x, range vrací seznam, xrange vrací objekt xrange, který je iterovatelný.

V Pythonu 3.x se range stane xrange jazyka Python 2.x a xrange je odstraněn.

0
Rajendra Uppal

Rozsah return a list while xrange vrátí objekt xrange , který bere stejnou paměť bez ohledu na velikost rozsahu, jako je tomu v tomto případě, je generován a dostupný pouze jeden prvek iterace, zatímco v případě použití rozsahu jsou všechny prvky generovány najednou a jsou dostupné v paměti.

0
user299567

rozsah: -range zaplní vše najednou, což znamená, že každé číslo rozsahu obsadí paměť.

xrange: -xrange je něco jako generátor, to přijde do obrazu, když chcete rozsah čísel, ale nechcete, aby byly uloženy, jako když chcete použít pro loop.so paměti efektivní.

0
tejaswini teju

Navíc pokud list(xrange(...)) bude ekvivalentní range(...).

list je tedy pomalé.

Také xrange opravdu nedokončí sekvenci

Proto to není jeho seznam, je to objekt xrange

0
U9-Forward