Python 3 verwandelt den Bereich in eine Liste

178

Ich versuche eine Liste mit Zahlen 1-1000zu erstellen. Das Schreiben / Lesen wäre natürlich ärgerlich, daher versuche ich, eine Liste mit einem Bereich darin zu erstellen. In Python 2 scheint es, dass:

some_list = range(1,1000)

hätte funktioniert, aber in Python 3 ist der Bereich ähnlich wie xrangein Python 2?

Kann jemand einen Einblick geben?

Bootshaus
quelle
1
Außerdem some_list[i] == i+1brauchen Sie wahrscheinlich sowieso keine Liste.
NJZK2
1
@ RikPoggi. Beispielsweise muss möglicherweise eine Liste für eine Plotfunktion angegeben werden. Manchmal reicht ein Bereich aus, aber ein Bereich kann nicht verkettet werden (ist unveränderlich). Wenn Sie also allen gezeichneten Listen einen Standardstartwert hinzufügen müssen, muss dieser ebenfalls in eine Liste umgewandelt werden.
SherylHohman

Antworten:

223

Sie können einfach eine Liste aus dem Bereichsobjekt erstellen:

my_list = list(range(1, 1001))

So machen Sie es auch mit Generatoren in python2.x. In der Regel benötigen Sie jedoch wahrscheinlich keine Liste, da Sie den Wert von my_list[i]effizienter ( i + 1) ermitteln können. Wenn Sie nur darüber iterieren müssen, können Sie einfach darauf zurückgreifen range.

Beachten Sie auch, dass auf python2.x xrangeimmer noch indizierbar ist 1 . Dies bedeutet, dass rangeauf python3.x auch die gleiche Eigenschaft 2 hat

1print xrange(30)[12] funktioniert für python2.x

2 Die analoge Aussage zu 1 in python3.x ist print(range(30)[12])und das funktioniert auch.

mgilson
quelle
4
Dies ist definitiv der richtige Weg, aber ein Trottel: Dies ist nicht wirklich eine "Besetzung"
jterrace
@jterrace hat "cast" in "convert" geändert. Sie haben Recht damit, dass es keine Besetzung ist ... Ich weiß nicht genau, wie ich es nennen soll.
mgilson
2
Ich würde sagen "konstruieren" oder "bauen" (oder möglicherweise "materialisieren") - da Sie einen Generator nicht als solchen in eine Liste "konvertieren" (als solchen), erstellen Sie ein neues Listenobjekt aus einer Datenquelle, was passiert ein Generator zu sein ... (aber nur Haare spalten und nicht 100% sicher sein, was ich sowieso bevorzuge)
Jon Clements
2
Mein +1 für "Konstrukt", da es mit anderen OO-Sprachen übereinstimmt. Das list(arg)wird in anderen Sprachen als Aufruf eines Konstruktors der listKlasse verstanden. Eigentlich ist es auch der Python-Fall. Die Debatten, ob das Objekt während der Konstruktion (wie im C ++ - Fall) oder nur während der ersten automatisch aufgerufenen Methode (wie in der Python- __init__()Methode) gefüllt wird, können die abstrakte Grundidee nicht ändern. Meiner Ansicht nach nimmt der Listenkonstruktor den Iterator und füllt die Liste mit den zurückgegebenen Werten .
Pepr
2
Warum gibt es einen Fehler im Jupiter-Notebook und funktioniert gut in der Shell? Fehler:'range' object is not callable
subtleseeker
34

In Pythons <= 3.4 können Sie, wie andere vorgeschlagen haben, list(range(10))eine Liste aus einem Bereich erstellen (im Allgemeinen jede iterierbare).

Eine andere Alternative, die in Python 3.5mit seinen Entpackungsverallgemeinerungen eingeführt wurde, ist die Verwendung *in einem Listenliteral []:

>>> r = range(10)
>>> l = [*r]
>>> print(l)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Dies entspricht zwar list(r)der wörtlichen Syntax und der Tatsache, dass kein Funktionsaufruf beteiligt ist, ermöglicht jedoch eine schnellere Ausführung. Es sind auch weniger Zeichen, wenn Sie Golf codieren müssen :-)

Dimitris Fasarakis Hilliard
quelle
4
Um es klar auszudrücken, können Sie es immer noch einzeilig verwenden: Funktioniert [*range(10)]einwandfrei, wenn Sie das rangefür keinen Zweck benötigen, sondern das Initialisieren des list. Randnotiz: Mein Lieblingsteil (okay, nicht wirklich) beim Entpacken von Verallgemeinerungen ist, dass leere sets jetzt eine wörtliche Syntax haben {*()}, oder wie ich es nenne, den einäugigen Affenoperator. ;-)
ShadowRanger
@ShadowRanger so habe ich ursprünglich darüber nachgedacht, es zu schreiben. Ich habe mich entschlossen, etwas ausführlicher zu sein, um neue Python-Benutzer nicht zu verwirren :-)
Dimitris Fasarakis Hilliard
26

In Python 3.x hat die range()Funktion einen eigenen Typ. In diesem Fall müssen Sie den Iterator verwenden

list(range(1000))

nurulhudamustaqim
quelle
11
"In diesem Fall müssen Sie den Iterator verwenden"? Was zum Teufel soll das heißen?
user2357112 unterstützt Monica
2
Ich verwende Python 3.7 und habe x = list (range (1000)) ausprobiert, habe aber den Fehler TypeError erhalten: 'list' Objekt ist nicht aufrufbar
Earthshaker
@Earthshaker Sie müssen einen Tippfehler haben, wielist(range(1000))()
wjandrea
17

Der Grund, warum Python3 keine Funktion zum direkten Abrufen einer Fernkampfliste bietet, liegt darin, dass der ursprüngliche Python3-Designer in Python2 ein Anfänger war. Er hat nur die Verwendung der range()Funktion in einer for-Schleife in Betracht gezogen , daher sollte die Liste niemals erweitert werden müssen. Tatsächlich müssen wir die range()Funktion sehr oft verwenden , um eine Liste zu erstellen und an eine Funktion zu übergeben.

Daher ist Python3 in diesem Fall im Vergleich zu Python2 weniger praktisch, weil:

  • In Python2 haben wir xrange()und range();
  • In Python3 haben wir range()undlist(range())

Trotzdem können Sie die Listenerweiterung folgendermaßen verwenden:

[*range(N)]
xuancong84
quelle
3
Der springende Punkt ist, es weniger bequem zu machen, ein zu machen list, weil das normalerweise das Falsche ist. Für 99 von 100 Anwendungsfälle, eine tatsächliche Herstellung listist ineffizient und sinnlos, da rangesich wie eine unveränderliche Sequenz wirkt in fast jeder Hinsicht, manchmal effizienter zu booten (zB Containment - Tests für ints sind O(1), gegenüber O(n)für lists). In Python 2 wurde rangestandardmäßig verwendet, obwohl dies xrangefast immer die bessere Option war. In Python 3 können Sie sich explizit für das entscheiden listund es nicht versehentlich erhalten, indem Sie den falschen Namen verwenden.
ShadowRanger
7
Der Kommentar zum Python 3-Designer und seiner Expertise in Python 2 ist ziemlich kühn und unverschämt.
Kazarey
@ Kazarey Aber ist es wahr? Es gibt eine Menge Dinge in Python, die in diesem Sinne fragwürdig sind
javadba
1
Ich würde mich besonders dafür aussprechen, dass die Abkürzung zum Auspacken die Liste erstellt, aber ich stimme @kazarey zu. Der Kommentar zum Designer ist sowohl unbegründet (oder zumindest nicht durch Referenzen belegt) als auch unnötig.
Nubarke
12

Sie sollten wirklich nicht die Nummern 1-1000 in einer Liste verwenden müssen. Aber wenn Sie aus irgendeinem Grund diese Zahlen wirklich brauchen, können Sie Folgendes tun:

[i for i in range(1, 1001)]

Listenverständnis auf den Punkt gebracht:

Das obige Listenverständnis bedeutet:

nums = []
for i in range(1, 1001):
    nums.append(i)

Dies ist nur die Syntax des Listenverständnisses, allerdings ab 2.x. Ich weiß, dass dies in Python 3 funktioniert, bin mir aber nicht sicher, ob es auch eine aktualisierte Syntax gibt

Der Bereich beginnt einschließlich des ersten Parameters. aber Enden bis zu, nicht einschließlich dem zweiten Parameter (wenn zwei Parameter geliefert, wenn der erste Parameter weggelassen wird, wird es beginnen bei ‚0‘)

range(start, end+1)
[start, start+1, .., end]
inspectorG4dget
quelle
20
Warum Verständnis? Nur:list(range(1000))
Rik Poggi
Vielen Dank! Würde es Ihnen etwas ausmachen zu erklären, warum ich für mich bin ... anstatt nur für mich?
Bootshaus
Ich habe nicht mit Python3 gearbeitet. Ich bin mir also nicht ganz sicher, wie es funktioniert. Ich weiß, dass Verständnis funktionieren wird, aber beim Casting war es nicht 100%. Aber wenn Casting funktioniert, haben Sie Recht und Ihr Weg ist pythonischer.
InspectorG4dget
1
@ inspectorG4dget: Es ist kein "Casting", es ruft den list()Konstruktor mit einer Iterable auf . Der list()Konstruktor weiß, wie eine neue Liste erstellt wird, wenn ein iterierbares Objekt angegeben wird.
Greg Hewgill
4
@ InspectorG4dget: list(range(1000))funktioniert in Python3 genau wie list(xrange(1000))in Python2
Rik Poggi
4

Wenn Sie 1-1000 (einschließlich) möchten, verwenden Sie die range(...)Funktion mit den Parametern 1 und 1001 : range(1, 1001), da die range(start, end)Funktion von Anfang bis (Ende-1) einschließlich geht.

CosmicComputer
quelle
0

Verwenden Sie Range in Python 3.

Hier ist eine Beispielfunktion, die zwischen Zahlen von zwei Zahlen zurückgibt

def get_between_numbers(a, b):
    """
    This function will return in between numbers from two numbers.
    :param a:
    :param b:
    :return:
    """
    x = []
    if b < a:
        x.extend(range(b, a))
        x.append(a)
    else:
        x.extend(range(a, b))
        x.append(b)

    return x

Ergebnis

print(get_between_numbers(5, 9))
print(get_between_numbers(9, 5))

[5, 6, 7, 8, 9]  
[5, 6, 7, 8, 9]
Rajiv Sharma
quelle
Dies scheint eine andere Frage zu beantworten ...?
Wjandrea
-1

Tatsächlich ist dies eine Retro-Abstufung von Python3 im Vergleich zu Python2. Natürlich ist Python2, das range () und xrange () verwendet, bequemer als Python3, das list (range ()) bzw. range () verwendet. Der Grund dafür ist, dass der ursprüngliche Designer von Python3 nicht sehr erfahren ist. Er hat nur die Verwendung der Bereichsfunktion durch viele Anfänger in Betracht gezogen, um über eine große Anzahl von Elementen zu iterieren, bei denen sowohl Speicher als auch CPU ineffizient sind. Sie vernachlässigten jedoch die Verwendung der Bereichsfunktion zur Erstellung einer Nummernliste. Jetzt ist es zu spät für sie, sich schon wieder umzuziehen.

Wenn ich der Designer von Python3 sein sollte, werde ich:

  1. Verwenden Sie irange, um einen Sequenziterator zurückzugeben
  2. Verwenden Sie lrange, um eine Sequenzliste zurückzugeben
  3. Verwenden Sie range, um entweder einen Sequenziterator zurückzugeben (wenn die Anzahl der Elemente groß ist, z. B. range (9999999) oder eine Sequenzliste (wenn die Anzahl der Elemente klein ist, z. B. range (10)).

Das sollte optimal sein.

xuancong84
quelle
Wie beantwortet dies die Frage?
Wjandrea
Ja, es beantwortet die Frage, indem es Python3-Entwickler auffordert, Python3 zu ändern und zu verbessern. Aber es ist unwahrscheinlich, dass sie sich ändern, da sie nicht so elegant sind.
xuancong84