Ich arbeite in einer Domäne, in der Bereiche konventionell einschließlich beschrieben werden. Ich habe menschenlesbare Beschreibungen wie from A to B
, die Bereiche darstellen, die beide Endpunkte enthalten - z. from 2 to 4
bedeutet 2, 3, 4
.Wie sollte ich mit Include-Bereichen in Python umgehen?
Was ist der beste Weg, um mit diesen Bereichen in Python-Code zu arbeiten? Der folgende Code funktioniert inklusive Bereiche von ganzen Zahlen zu erzeugen, aber ich brauche auch inklusive Scheibe Operationen auszuführen:
def inclusive_range(start, stop, step):
return range(start, (stop + 1) if step >= 0 else (stop - 1), step)
Die einzige komplette Lösung, die ich sehe, ist ausdrücklich + 1
(oder - 1
) ich jedes Mal zu verwenden, verwende range
oder Scheibe Notation (zB range(A, B + 1)
, l[A:B+1]
, range(B, A - 1, -1)
). Ist diese Wiederholung wirklich der beste Weg, um mit inklusiven Bereichen zu arbeiten?
Bearbeiten: Dank L3viathan für die Beantwortung. Das Schreiben eine inclusive_slice
Funktion ergänzen inclusive_range
ist sicherlich eine Option, obwohl ich wahrscheinlich würde es wie folgt schreiben:
def inclusive_slice(start, stop, step):
...
return slice(start, (stop + 1) if step >= 0 else (stop - 1), step)
...
hier repräsentiert Code negative Indizes zu behandeln, die nicht einfach ist, wenn sie mit Scheiben verwendet - Note, zum Beispiel , dass die Funktion von L3viathan falsche Ergebnisse liefert, wenn slice_to == -1
.
Allerdings scheint es, dass eine inclusive_slice
Funktion umständlich zu bedienen wäre - ist l[inclusive_slice(A, B)]
wirklich besser als l[A:B+1]
?
Gibt es einen besseren Weg, um inklusive Bereiche zu behandeln?
Bearbeiten 2: Vielen Dank für die neuen Antworten. Ich stimme Francis und Corley zu, dass eine Änderung der Bedeutung von Slice-Operationen, entweder global oder für bestimmte Klassen, zu erheblicher Verwirrung führen würde. Ich lehne mich daher nun an, eine inclusive_slice
Funktion zu schreiben.
Um meine eigene Frage aus dem vorherigen bearbeiten zu beantworten, ich bin zu dem Schluss gekommen, dass eine solche Funktion (zB l[inclusive_slice(A, B)]
) wäre besser als das manuelle Hinzufügen/Subtrahieren von 1 (zB l[A:B+1]
), da es Grenzfälle zulassen würde (wie B == -1
und B == None
) an einem einzigen Ort behandelt werden. Können wir die Peinlichkeit bei der Verwendung der Funktion reduzieren?
Edit 3: Ich habe darüber nachgedacht, wie die Syntax der Verwendung verbessern, die derzeit wie l[inclusive_slice(1, 5, 2)]
aussieht. Insbesondere wäre es gut, wenn die Erzeugung einer inklusiven Schicht der Standard-Slice-Syntax ähnelt. Um dies zu ermöglichen, könnte anstelle von inclusive_slice(start, stop, step)
eine Funktion inclusive
vorhanden sein, die eine Scheibe als Parameter verwendet. Die ideale Verwendungssyntax für inclusive
wäre Linie 1
:
l[inclusive(1:5:2)] # 1
l[inclusive(slice(1, 5, 2))] # 2
l[inclusive(s_[1:5:2])] # 3
l[inclusive[1:5:2]] # 4
l[1:inclusive(5):2] # 5
Leider ist dies nicht von Python erlaubt, die nur die Verwendung von :
Syntax innerhalb []
ermöglicht. inclusive
müsste daher entweder mit der Syntax 2
oder 3
aufgerufen werden (wobei s_
wie the version provided by numpy wirkt).
Andere Möglichkeiten sind inclusive
in ein Objekt machen mit __getitem__
, Syntax ermöglicht 4
oder inclusive
nur den stop
Parameter der Scheibe anzulegen, wie in der Syntax 5
. Leider glaube ich nicht, dass letzteres funktioniert werden kann, da inclusive
die Kenntnis des Werts step
erfordert.
Von dem bearbeitbar Syntaxen (das Original l[inclusive_slice(1, 5, 2)]
plus 2
, 3
und 4
), die das Beste wäre, zu benutzen? Oder gibt es eine andere, bessere Option?
Final Edit: Vielen Dank für die Antworten und Kommentare, das war sehr interessant. Ich war schon immer ein Fan von Pythons "one way to do it" -Philosophie, aber dieses Problem wurde durch einen Konflikt zwischen Python's "one way" und dem "one way" der Problemdomäne verursacht. Ich habe definitiv eine Wertschätzung für TIMTOWTDI im Sprachdesign gewonnen.
Für die erste und am besten gewählte Antwort, ich die Belohnung an L3viathan.
Beachten Sie, dass die von Ihnen geschriebene Funktion falsch ist. Das zweite Argument "stop + step" hat das Potenzial, den inklusiven Bereich über das hinaus, was es sein sollte, zu erhöhen. Es sollte "Stopp + 1" sein. z.B. 'range (0, 7, 3)' ist '[0, 3, 6]' aber Ihre Funktion würde '[0, 3, 6, 9]' ergeben. – Shashank
Sind Elemente in Bereich immer ganze Zahlen in Ihrer Domäne? Ich meine z.B. 'von 2 bis 4' kann bedeuten '[2,3,4]' oder '2: 00,2: 01, ..., 4: 00'. –
@qarma - Ja, genau wie die eingebaute range() -Funktion muss ich nur Bereiche von ganzen Zahlen behandeln. – user200783