Warum enthält range(start, end) kein Ende?

Lesezeit: 7 Minuten

Benutzer-Avatar
MetaGuru

>>> range(1,11)

gibt Ihnen

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

Warum nicht 1-11?

Haben sie sich nur zufällig dafür entschieden, es so zu machen, oder hat es einen Wert, den ich nicht sehe?

  • lesen Sie Dijkstra, ewd831

    – SilentGhost

    21. Dezember 2010 um 22:52 Uhr

  • Im Grunde wählen Sie eine Reihe von Off-by-one-Bugs für eine andere aus. Ein Satz führt eher dazu, dass Ihre Schleifen vorzeitig beendet werden, der andere verursacht wahrscheinlich eine Ausnahme (oder einen Pufferüberlauf in anderen Sprachen). Sobald Sie eine Menge Code geschrieben haben, werden Sie sehen, dass die Wahl des Verhaltens range() hat viel öfter Sinn gemacht

    – John LaRooy

    21. Dezember 2010 um 23:34 Uhr

  • Link zu Dijkstra, ewd831: cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF

    – unutbu

    21. Dezember 2010 um 23:41 Uhr

  • @andreasdr Aber selbst wenn das kosmetische Argument gültig ist, führt der Ansatz von Python nicht zu einem neuen Lesbarkeitsproblem? Im gebräuchlichen Englisch impliziert der Begriff “Bereich”, dass etwas reicht aus etwas zu etwas – wie ein Intervall. Dass len(list(range(1,2))) 1 und len(list(range(2))) 2 zurückgibt, müssen Sie wirklich lernen zu verdauen.

    – armin

    24. Juli 2016 um 14:11 Uhr

  • Wenn eine Person sagt, dass sie eine Reihe von Farben von Grün bis Rot haben möchte, dann würden nur sehr wenige Leute sagen, dass sie kein Rot wollen. Der englische Wortbereich ist also kein geeignetes Wort. Das wird sich nicht ändern, aber ich denke, das ist ein Schwachpunkt, dass Python eine vernünftige Sprache ist.

    – Peter Moore

    6. August 2020 um 13:28 Uhr


Benutzer-Avatar
moinudin

Weil es üblicher ist anzurufen range(0, 10) die zurückkehrt [0,1,2,3,4,5,6,7,8,9] die 10 Elemente enthält, die gleich sind len(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önntest du das sehen, wenn range() ging bis genau len(li) dass das problematisch wäre? Der Programmierer müsste explizit 1 subtrahieren. Dies folgt auch dem allgemeinen Trend, dass Programmierer bevorzugen for(int i = 0; i < 10; i++) Über for(int i = 0; i <= 9; i++).

Wenn Sie häufig einen Bereich mit einem Anfang 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]

  • Wenn das die Argumentation wäre, wären es nicht die Parameter range(start, count)?

    – Markieren Sie Lösegeld

    21. Dezember 2010 um 22:50 Uhr

  • @shogun Der Startwert ist standardmäßig 0, dh range(10) ist äquivalent zu range(0, 10).

    – moinudin

    21. Dezember 2010 um 22:57 Uhr

  • Dein range1 funktioniert nicht mit Bereichen, die eine andere Schrittweite haben als 1.

    – dimo414

    21. Mai 2015 um 5:09 Uhr

  • Sie erklären, dass Bereich (x) mit 0 beginnen sollte und x die “Länge des Bereichs” sein wird. OK. Aber Sie haben nicht erklärt, warum range(x,y) mit x beginnen und mit y-1 enden sollte. Wenn der Programmierer eine for-Schleife mit i von 1 bis 3 haben möchte, muss er explizit 1 hinzufügen. Geht es wirklich um Bequemlichkeit?

    – armin

    24. Juli 2016 um 14:42 Uhr


  • for i in range(len(li)): ist eher ein Antimuster. Man sollte verwenden enumerate.

    – Hans

    6. März 2018 um 12:17 Uhr

Obwohl es hier einige nützliche algorithmische Erklärungen gibt, denke ich, dass es hilfreich sein kann, einige einfache Argumente aus dem „echten Leben“ hinzuzufügen, warum es so funktioniert, was ich als nützlich empfunden habe, als ich jungen Neuankömmlingen das Thema vorstellte:

Bei so etwas wie ‘range(1,10)’ kann Verwirrung entstehen, wenn man denkt, dass ein Parameterpaar den “Start und das Ende” darstellt.

Es ist eigentlich Start und “Stop”.

Nun, wenn es war der “End”-Wert dann, ja, Sie könnten erwarten, dass diese Zahl als letzter Eintrag in der Sequenz enthalten wäre. 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 iteriert. Diese Logik bricht zusammen, wenn Sie den Startparameter hinzufügen.

Der Schlüsselpunkt ist also, sich an seinen Namen zu erinnern: “Pause“. Das heißt, es ist der Punkt, an dem, wenn er erreicht ist, die Iteration sofort stoppt. Nicht nach dieser Punkt.

Während also „start“ tatsächlich den ersten einzubeziehenden Wert darstellt, „bricht“ es beim Erreichen des „stop“-Werts ab, anstatt „diesen ebenfalls“ weiterzuverarbeiten, bevor es stoppt.

Eine Analogie, die ich verwendet habe, um dies Kindern zu erklären, ist, dass es sich ironischerweise besser benimmt als Kinder! Es hört nicht auf nach es sollte – es stoppt sofort, ohne zu beenden, was es tat. (Sie verstehen das 😉 )

Eine andere Analogie – wenn Sie ein Auto fahren, tun Sie es nicht passieren ein Stop/Yield/Vorfahrt-Schild und am Ende sitzt es irgendwo neben oder hinter deinem 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 Pythonitos/Pythonitas zu erklären!

  • Diese Erklärung ist intuitiver. Vielen Dank

    – Fred

    10. Oktober 2019 um 2:50 Uhr

  • @bzip2, Python ist kein Schwein, es ist eine Schlange. Was Sie “Inkonsistenzen” und “Fehler” nennen, sind keine: Sie sind Designentscheidungen, die von Entwicklern getroffen werden, die konsequent durch die Sprache getragen werden und es Millionen von Programmierern ermöglichen, ihre Aufgaben zu lösen. Wenn es Ihnen nicht gefällt, verwenden Sie eine Erweiterung, die inklusive Bereiche bereitstellt, oder wechseln Sie zu einer anderen Sprache. Ihre Kommentare tragen nicht zum Verständnis von Python bei, sondern beleidigen die Community. Sie weisen auch darauf hin, dass Sie die Natur exklusiver Intervalle nicht verstehen, denn wenn Sie von 9 bis 11 Uhr ein Meeting haben, sind Sie um 11 Uhr frei.

    – Arthur Khazbs

    27. Januar 2021 um 17:22 Uhr

  • Ich liebe die Stoppschild-Analogie, tut mir leid, sie zu stehlen 🙂

    – Kojote

    20. September 2021 um 10:58 Uhr

Exklusive Sortimente haben einige Vorteile:

Für eine Sache jeder Artikel in range(0,n) ist ein gültiger Index für Listen der Länge n.

Ebenfalls range(0,n) hat eine Länge von nnicht n+1 was ein inklusiver Bereich wäre.

Benutzer-Avatar
irgendwie

Es funktioniert gut in Kombination mit nullbasierter Indizierung und len(). Zum Beispiel, wenn Sie 10 Elemente in einer Liste haben xsie sind von 0-9 nummeriert. range(len(x)) gibt dir 0-9.

Natürlich werden Ihnen die Leute sagen, dass es eher pythonisch ist for item in x oder for index, item in enumerate(x) statt for i in range(len(x)).

Slicing funktioniert auch so: foo[1:4] ist Punkt 1-3 von foo (beachten Sie, dass Element 1 aufgrund der nullbasierten Indexierung tatsächlich das zweite Element ist). Aus Gründen der Konsistenz sollten beide auf die gleiche Weise funktionieren.

Ich stelle es mir so vor: „Die erste Nummer, die Sie wollen, gefolgt von der ersten Nummer, die Sie wollen nicht wollen.” Wenn Sie 1-10 wollen, ist die erste Zahl, die Sie nicht wollen, 11, also ist es so range(1, 11).

Wenn es in einer bestimmten Anwendung umständlich wird, ist es einfach genug, eine kleine Hilfsfunktion zu schreiben, die dem Endindex eine 1 hinzufügt und aufruft range().

Benutzer-Avatar
xuanji

Es ist auch nützlich, um Bereiche aufzuteilen; range(a,b) kann aufgeteilt werden range(a, x) und range(x, b)während Sie bei inklusivem Bereich entweder schreiben würden x-1 oder x+1. Während Sie selten Bereiche aufteilen müssen, neigen Sie dazu, Listen ziemlich oft aufzuteilen, was einer der Gründe für das Aufteilen einer Liste ist l[a:b] enthält das a-te Element, aber nicht das b-te. Dann range die gleiche Eigenschaft zu haben, macht es schön konsistent.

Benutzer-Avatar
Geschicklichkeit

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 häufig den Endwert einschließen möchten, und bietet die alternative Syntax an:

1..10 #this is also a range from 1 to 10

Benutzer-Avatar
Robert

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über die Sie (wie Sie oben sehen) iterieren können.

Lesen Sie weiter die Python-Dokumentation for Range – sie betrachten die Iteration der for-Schleife als primären Anwendungsfall.

1100400cookie-checkWarum enthält range(start, end) kein Ende?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy