2014-04-22 6 views
44

Sowohl mein Professor als auch this guy behaupten, dass range eine Liste von Werten erstellt.Erzeugt Range() wirklich Listen?

. „Anmerkung: Die Reichweite Funktion gibt einfach eine Liste, die Zahlen von x bis y-1 enthält, beispielsweise im Bereich (5, 10) gibt die Liste [5, 6, 7, 8, 9 ]. "

Ich glaube, dies ungenau zu sein, weil:

type(range(5, 10)) 
<class 'range'> 

Darüber hinaus ist die einzige offensichtliche Art und Weise der ganzen Zahlen von range erstellt zuzugreifen, ist durch sie zu durchlaufen, die mich, dass die Kennzeichnung range führt zu glauben, als Eine Liste ist falsch.

+1

Ihr letzter Satz in Frage zu stellen ist falsch. 'range' Objekte implementieren'__getitem__'. – wim

+0

mögliches Duplikat von [Lazy evaluation python] (http://stackoverflow.com/questions/20535342/lazy-evaluation-python) – devnull

+0

Diese Frage ist sich der Unterschiede zwischen Python 2 und 3 nicht bewusst, und ist * nicht * ein Betrogener von dem einen verbunden. –

Antwort

98

In Python 2.x gibt range eine Liste zurück, aber in Python 3.x gibt range eine unveränderliche Sequenz vom Typ range zurück.

Python 2.x:

>>> type(range(10)) 
<type 'list'> 
>>> type(xrange(10)) 
<type 'xrange'> 

Python 3.x:

>>> type(range(10)) 
<class 'range'> 

In Python 2.x, wenn Sie ein iterable Objekt erhalten möchten, wie in Python 3.x, können Sie xrange Funktion verwenden, die eine unveränderliche Sequenz des Typs xrange zurückgibt.

Vorteil xrange über range in Python 2.x:

Der Vorteil xrange() über range() ist minimal (da xrange() noch die Werte zu schaffen hat, wenn sie danach gefragt werden), außer wenn ein sehr großer Bereich ist Wird auf einem speicherhungrigen Computer verwendet oder wenn alle Elemente des Bereichs nie verwendet werden (z. B. wenn die Schleife normalerweise mit einem Abbruch beendet wird).

Hinweis:

Darüber hinaus ist die einzige offensichtliche Art und Weise die ganzen Zahlen von range() erstellt zuzugreifen, ist durch sie zu durchlaufen,

Nope. Da range Objekte in Python 3 unveränderliche Sequenzen sind, unterstützen sie auch die Indizierung. Zitiert aus der range Funktion Dokumentation,

Ranges alle gemeinsamen Sequenzoperationen außer Verkettung implementieren und Wiederholung

...

Range-Objekte implementieren die collections.abc.Sequence ABC und bieten Funktionen wie Eindämmungstests , Element Index Lookup, Slicing und Unterstützung für negative Indizes.

Zum Beispiel

>>> range(10, 20)[5] 
15 
>>> range(10, 20)[2:5] 
range(12, 15) 
>>> list(range(10, 20)[2:5]) 
[12, 13, 14] 
>>> list(range(10, 20, 2)) 
[10, 12, 14, 16, 18] 
>>> 18 in range(10, 20) 
True 
>>> 100 in range(10, 20) 
False 

All dies ist möglich mit dieser unveränderlichen range Sequenz.

Kürzlich habe ich ein Problem konfrontiert und ich denke, es wäre angemessen, hier aufzunehmen. Betrachten Sie diese Python 3.x Code

from itertools import islice 
numbers = range(100) 
items = list(islice(numbers, 10)) 
while items: 
    items = list(islice(numbers, 10)) 
    print(items) 

Einer dieser Code erwarten würde alle zehn Zahlen als eine Liste drucken, bis 99. Aber es wäre unendlich laufen. Kannst du begründen warum?

Lösung

Da die range eine unveränderliche Sequenz zurückgibt, nicht ein Iterator-Objekt. Wenn also islice auf einem range Objekt ausgeführt wird, beginnt es immer von Anfang an. Betrachten Sie es als Drop-In-Ersatz für eine unveränderliche Liste. Jetzt kommt die Frage, wie wirst du es reparieren? Es ist einfach, man muss nur einen Iterator daraus machen. Ändern Sie einfach

numbers = range(100)

zu

numbers = iter(range(100))

Nun numbers ein Iterator-Objekt ist, und es erinnert sich, wie lange es vor iteriert wurde. Also, wenn die islice es iteriert, beginnt es nur von der Stelle, wo es zuvor endete.

+18

Es gibt ein 'Bereich'-Objekt zurück, das zufällig iterierbar ist, aber mehr als ein einfacher Iterator ist:) (zB: 'range (1, 100, 17) [3]' ist absolut legal) –

+0

@JonClements Danke, habe die Antwort mit den Informationen über 'range' und' xrange' Objekte aktualisiert :-) – thefourtheye

+1

nicht verwandt: 'x in Bereich (large_number) 'in Python 3 kann eine optimierte Implementierung verwenden, die nicht über den Bereich iteriert. – jfs

7

Kommt drauf an.

in Python-2.x, erstellt range tatsächlich eine Liste (die auch eine Folge ist), während xrangexrange ein Objekt erzeugt, das verwendet werden kann, um durch die Werte iterieren.

Auf der anderen Seite, in Python-3.x erstellt range eine iterable (oder genauer gesagt, eine Sequenz)

+5

Es gibt keine "Art von" darüber - 'range()' in Python 3 gibt eine iterierbare, importieren Sammlungen; isinstance (Bereich (2), collections.Iterable) 'ist wahr (und nitpick - verwenden Sie nicht die Überschrift-Syntax für die Betonung - wenn Sie wirklich brauchen, ist Fett geeigneter) – dbr

+1

@ dbr, Danke. Antwort aktualisiert – sshashank124

+1

@ dbr: es ist ein bisschen komplexer als nur ein iterable, obwohl. – njzk2

1

Bereich erstellt eine Liste, wenn die Version Python verwendet 2.x ist. In diesem Szenario Bereich ist nur zu verwenden, wenn seine mehr als einmal referenziert, sonst verwenden Sie xrange, die einen Generator dort durch Redusing der Speicherverbrauch und manchmal Zeit, wie es faul Annäherung hat.

xrange nicht da ist in Python 3.x eher Bereich steht für was xrange ist für Python 2.x

siehe What is the difference between range and xrange functions in Python 2.X?