>>> range(1,11)
gibt Ihnen
[1,2,3,4,5,6,7,8,9,10]
Warum nicht 1-11?
Haben sie sich einfach dazu entschlossen, es zufällig zu machen, oder hat es einen Wert, den ich nicht sehe?
range()
viel häufiger Sinn macht
>>> range(1,11)
gibt Ihnen
[1,2,3,4,5,6,7,8,9,10]
Warum nicht 1-11?
Haben sie sich einfach dazu entschlossen, es zufällig zu machen, oder hat es einen Wert, den ich nicht sehe?
range()
viel häufiger Sinn macht
Antworten:
Weil es üblicher ist, aufzurufen, range(0, 10)
welche Rückgabe [0,1,2,3,4,5,6,7,8,9]
10 Elemente enthält, die gleich sindlen(range(0, 10))
. Denken Sie daran, dass Programmierer eine 0-basierte Indizierung bevorzugen.
Beachten Sie auch das folgende allgemeine Code-Snippet:
for i in range(len(li)):
pass
Könnten Sie sehen, dass dies problematisch wäre , wenn range()
genau len(li)
das erreicht würde? Der Programmierer müßte explizit subtrahiert 1. Dies auch die gemeinsame Entwicklung von Programmierern folgt lieber for(int i = 0; i < 10; i++)
überfor(int i = 0; i <= 9; i++)
.
Wenn Sie häufig den Bereich mit einem Start von 1 aufrufen, möchten Sie möglicherweise Ihre eigene Funktion definieren:
>>> def range1(start, end):
... return range(start, end+1)
...
>>> range1(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
range(start, count)
?
range(10)
entspricht range(0, 10)
.
range1
nicht mit Bereichen, die eine andere Schrittgröße als haben 1
.
for i in range(len(li)):
ist eher ein Antimuster. Man sollte verwenden enumerate
.
Obwohl es hier einige nützliche algorithmische Erklärungen gibt, denke ich, dass es hilfreich sein kann, einige einfache Argumente aus dem wirklichen Leben hinzuzufügen, warum dies so funktioniert, die ich als nützlich empfunden habe, als ich jungen Neulingen das Thema vorstellte:
Bei so etwas wie "Bereich (1,10)" kann Verwirrung entstehen, wenn man denkt, dass ein Parameterpaar den "Anfang und das Ende" darstellt.
Es ist eigentlich Start und "Stop".
Wenn es nun der "End" -Wert wäre, könnten Sie erwarten, dass diese Zahl als letzter Eintrag in die Sequenz aufgenommen wird. Aber es ist nicht das "Ende".
Andere nennen diesen Parameter fälschlicherweise "count", denn wenn Sie immer nur 'range (n)' verwenden, wird er natürlich 'n' Mal wiederholt. Diese Logik bricht zusammen, wenn Sie den Startparameter hinzufügen.
Der wichtigste Punkt ist also, sich an den Namen zu erinnern: " stop ". Dies bedeutet, dass an diesem Punkt die Iteration sofort beendet wird, wenn sie erreicht ist. Nicht danach diesem Punkt.
Während "Start" tatsächlich den ersten Wert darstellt, der eingeschlossen werden soll, "bricht" es beim Erreichen des "Stopp" -Werts, anstatt "auch diesen" vor dem Stoppen weiter zu verarbeiten.
Eine Analogie, die ich verwendet habe, um Kindern dies zu erklären, ist, dass es sich ironischerweise besser benimmt als Kinder! Es hört nicht auf, nachdem es sollte - es hört sofort auf, ohne zu beenden, was es tat. (Sie bekommen das;))
Eine andere Analogie - wenn Sie ein Auto fahren, kommen Sie nicht vorbei Stopp- / Ertrags- / Nachgiebigkeitsschild und landen irgendwo neben oder hinter Ihrem Auto. Technisch gesehen haben Sie es immer noch nicht erreicht, wenn Sie aufhören. Es ist nicht in den "Dingen, die Sie auf Ihrer Reise passiert haben" enthalten.
Ich hoffe, einiges davon hilft bei der Erklärung von Pythonitos / Pythonitas!
Es funktioniert gut in Kombination mit nullbasierter Indizierung und len()
. Wenn Sie beispielsweise 10 Elemente in einer Liste haben x
, sind diese mit 0 bis 9 nummeriert. range(len(x))
gibt dir 0-9.
Natürlich werden die Leute sagen , es ist mehr Pythonic zu tun for item in x
oder for index, item in enumerate(x)
nicht for i in range(len(x))
.
Das Schneiden funktioniert auch so: foo[1:4]
ist die Elemente 1-3 von foo
(wobei zu beachten ist, dass Element 1 aufgrund der nullbasierten Indizierung tatsächlich das zweite Element ist). Aus Gründen der Konsistenz sollten beide gleich funktionieren.
Ich stelle es mir vor als: "Die erste Nummer, die Sie wollen, gefolgt von der ersten Nummer, die Sie nicht wollen." Wenn Sie 1-10 wollen, ist die erste Zahl, die Sie nicht wollen, 11, also ist es range(1, 11)
.
Wenn es in einer bestimmten Anwendung umständlich wird, ist es einfach genug, eine kleine Hilfsfunktion zu schreiben, die dem Endindex und den Aufrufen 1 hinzufügt range()
.
w = 'abc'; w[:] == w[0:len(w)]; w[:-1] == w[0:len(w)-1];
def full_range(start,stop): return range(start,stop+1) ## helper function
for index, item in enumerate(x)
, um Verwirrung zu vermeiden
Es ist auch nützlich, um Bereiche aufzuteilen. range(a,b)
kann in range(a, x)
und aufgeteilt werden range(x, b)
, während Sie mit inklusivem Bereich entweder x-1
oder schreiben würden x+1
. Während Sie Bereiche selten teilen müssen, neigen Sie dazu, Listen ziemlich oft zu teilen. Dies ist einer der Gründe, warum das Schneiden einer Liste l[a:b]
das a-te Element enthält, nicht jedoch das b-te. Dann range
macht es die gleiche Eigenschaft schön konsistent.
Die Länge des Bereichs ist der obere Wert minus der untere Wert.
Es ist sehr ähnlich zu etwas wie:
for (var i = 1; i < 11; i++) {
//i goes from 1 to 10 in here
}
in einer Sprache im C-Stil.
Auch wie Rubys Sortiment:
1...11 #this is a range from 1 to 10
Ruby erkennt jedoch, dass Sie den Terminalwert häufig einschließen möchten, und bietet die alternative Syntax:
1..10 #this is also a range from 1 to 10
1..10
vs 1...10
schwer sein , zu unterscheiden , beim Lesen Code!
Grundsätzlich können wir in Python- range(n)
Iterationszeiten n
, die exklusiver Natur sind, keinen letzten Wert angeben, wenn sie gedruckt werden. Wir können eine Funktion erstellen, die einen Inklusivwert angibt. Dies bedeutet, dass auch der zuletzt im Bereich genannte Wert gedruckt wird.
def main():
for i in inclusive_range(25):
print(i, sep=" ")
def inclusive_range(*args):
numargs = len(args)
if numargs == 0:
raise TypeError("you need to write at least a value")
elif numargs == 1:
stop = args[0]
start = 0
step = 1
elif numargs == 2:
(start, stop) = args
step = 1
elif numargs == 3:
(start, stop, step) = args
else:
raise TypeError("Inclusive range was expected at most 3 arguments,got {}".format(numargs))
i = start
while i <= stop:
yield i
i += step
if __name__ == "__main__":
main()
Betrachten Sie den Code
for i in range(10):
print "You'll see this 10 times", i
Die Idee ist, dass Sie eine Liste der Länge erhalten y-x
, die Sie (wie Sie oben sehen) durchlaufen können.
Informieren Sie sich in den Python-Dokumenten über den Bereich - sie betrachten die For-Loop-Iteration als primären Verwendungszweck.
In vielen Fällen ist es einfach bequemer, darüber nachzudenken.
Grundsätzlich können wir uns einen Bereich als Intervall zwischen start
und vorstellen end
. Wenn start <= end
, ist die Länge des Intervalls zwischen ihnen end - start
. Wenn len
tatsächlich als Länge definiert wurde, hätten Sie:
len(range(start, end)) == start - end
Wir zählen jedoch die im Bereich enthaltenen Ganzzahlen, anstatt die Länge des Intervalls zu messen. Um die obige Eigenschaft beizubehalten, sollten wir einen der Endpunkte einschließen und den anderen ausschließen.
Das Hinzufügen des step
Parameters entspricht dem Einfügen einer Längeneinheit. In diesem Fall würden Sie erwarten
len(range(start, end, step)) == (start - end) / step
für die Länge. Um die Zählung zu erhalten, verwenden Sie einfach die Ganzzahldivision.