Solche Ausdrücke findet man häufig in Python-Fragen zu SO. Entweder für den einfachen Zugriff auf alle Elemente der Iterable
for i in range(len(a)):
print(a[i])
Welches ist nur eine umständliche Art zu schreiben:
for e in a:
print(e)
Oder zum Zuweisen zu Elementen des iterablen:
for i in range(len(a)):
a[i] = a[i] * 2
Welches sollte das gleiche sein wie:
for i, e in enumerate(a):
a[i] = e * 2
# Or if it isn't too expensive to create a new iterable
a = [e * 2 for e in a]
Oder zum Filtern über die Indizes:
for i in range(len(a)):
if i % 2 == 1: continue
print(a[i])
Was so ausgedrückt werden könnte:
for e in a [::2]:
print(e)
Oder wenn Sie nur die Länge der Liste und nicht deren Inhalt benötigen:
for _ in range(len(a)):
doSomethingUnrelatedToA()
Welches könnte sein:
for _ in a:
doSomethingUnrelatedToA()
In Python wir haben enumerate
, schneiden, filter
, sorted
usw ... Als Python - for
Konstrukte zu iterieren Iterables vorgesehen sind und nicht reicht nur von ganzen Zahlen gibt es reale Anwendungsfälle , wo Sie brauchen in range(len(a))
?
range(len(a))
es sind normalerweise Leute, die mit Python ziemlich unerfahren sind (obwohl nicht unbedingt mit Programmierung im Allgemeinen).range(len(a))
als ich Python gelernt habe. Heutzutage nicht, weil es, wie Sie sagten, ziemlich einfach zu ersetzen ist.range(len(a))
oft, weil ich nicht den Inhalt von Liste a brauche, sondern nur die Länge.for i in range(len(a)): doSomethingAbout(a[i+1] - a[i])
Wie kann ich das umgehen?Antworten:
Wenn Sie mit Indizes einer Sequenz arbeiten müssen, dann ja - Sie verwenden es ... zB für das Äquivalent von numpy.argsort ...:
>>> a = [6, 3, 1, 2, 5, 4] >>> sorted(range(len(a)), key=a.__getitem__) [2, 3, 1, 5, 4, 0]
quelle
[ix for ix, _ in sorted(enumerate(a), key=lambda i: i[1])]
obwohl, obwohl Ihre wohl netter / geekier ist.Was ist, wenn Sie gleichzeitig auf zwei Elemente der Liste zugreifen müssen?
for i in range(len(a[0:-1])): something_new[i] = a[i] * a[i+1]
Sie können dies verwenden, aber es ist wahrscheinlich weniger klar:
for i, _ in enumerate(a[0:-1]): something_new[i] = a[i] * a[i+1]
Persönlich bin ich auch nicht 100% zufrieden!
quelle
for ix, i in enumerate(a)
scheint gleichwertig zu sein, nein?for a1,a2 in zip(a[:-1],a[1:])
Kurze Antwort : mathematisch gesehen nein, praktisch ja, zum Beispiel für die absichtliche Programmierung.
Technisch wäre die Antwort "Nein, es wird nicht benötigt", da es mit anderen Konstrukten ausgedrückt werden kann. In der Praxis verwende ich
for i in range(len(a)
(oderfor _ in range(len(a))
wenn ich den Index nicht benötige), um deutlich zu machen, dass ich so oft iterieren möchte, wie Elemente in einer Sequenz vorhanden sind, ohne die Elemente in der Sequenz für irgendetwas verwenden zu müssen.Also: "Gibt es einen Bedarf?" ? - Ja, ich brauche es, um die Bedeutung / Absicht des Codes für Lesbarkeitszwecke auszudrücken.
Siehe auch: https://en.wikipedia.org/wiki/Intentional_programming
Und wenn es überhaupt keine Sammlung gibt, die mit der Iteration verknüpft ist, ist dies natürlich
for ... in range(len(N))
die einzige Option, um nicht darauf zurückzugreifeni = 0; while i < N; i += 1 ...
quelle
for _ in range(len(a))
gegenüberfor _ in a
?a
für jedena
a
Elemente in " im Gegensatz zu " gibt Element in , unabhängig vom Inhalt von " ... also nur eine Nuance der absichtlichen Programmierung.'hello'
mit so vielen Elementen wie in der Liste zu erhaltena
, verwenden Sieb = ['hello'] * len(a)
Anhand der Kommentare und der persönlichen Erfahrung sage ich nein, es besteht keine Notwendigkeit dafür
range(len(a))
. Alles, was Sie tunrange(len(a))
können, kann auf eine andere (normalerweise weitaus effizientere) Weise erfolgen.Sie haben in Ihrem Beitrag viele Beispiele angegeben, daher werde ich sie hier nicht wiederholen. Stattdessen werde ich ein Beispiel für diejenigen geben, die sagen: "Was ist, wenn ich nur die Länge
a
und nicht die Elemente möchte ?". Dies ist eines der wenigen Male, die Sie in Betracht ziehen könntenrange(len(a))
. Aber auch dies kann folgendermaßen geschehen:>>> a = [1, 2, 3, 4] >>> for _ in a: ... print True ... True True True True >>>
Clements Antwort (wie von Allik gezeigt) kann auch überarbeitet werden, um Folgendes zu entfernen
range(len(a))
:>>> a = [6, 3, 1, 2, 5, 4] >>> sorted(range(len(a)), key=a.__getitem__) [2, 3, 1, 5, 4, 0] >>> # Note however that, in this case, range(len(a)) is more efficient. >>> [x for x, _ in sorted(enumerate(a), key=lambda i: i[1])] [2, 3, 1, 5, 4, 0] >>>
Zusammenfassend
range(len(a))
ist also nicht erforderlich . Der einzige Vorteil ist die Lesbarkeit (die Absicht ist klar). Aber das ist nur Präferenz und Codestil.quelle
for _ in a:
als "Iterieren über a, ignoriere aber dessen Inhalt", aber ich interpretierefor _ in range(len(a))
als "Holen Sie sich die Länge von a, erstellen Sie dann eine Anzahl von ganzen Zahlen derselben Länge und ignorieren Sie schließlich den Inhalt".range(len(a))
Szenario geben wird, in dem ich dies verwenden muss oder nicht kann.Manchmal erfordert matplotlib
range(len(y))
, z. B. währendy=array([1,2,5,6])
,plot(y)
funktioniert gut,scatter(y)
nicht. Man muss schreibenscatter(range(len(y)),y)
. (Ich persönlich denke, dies ist ein Fehler inscatter
;plot
und seinen Freundenscatter
undstem
sollte die gleichen Aufrufsequenzen so oft wie möglich verwenden.)quelle
Es ist schön zu haben, wenn Sie den Index für irgendeine Art von Manipulation verwenden müssen und das aktuelle Element nicht ausreicht. Nehmen Sie zum Beispiel einen Binärbaum, der in einem Array gespeichert ist. Wenn Sie eine Methode haben, die Sie auffordert, eine Liste von Tupeln zurückzugeben, die die direkten untergeordneten Knoten jedes Knotens enthält, benötigen Sie den Index.
#0 -> 1,2 : 1 -> 3,4 : 2 -> 5,6 : 3 -> 7,8 ... nodes = [0,1,2,3,4,5,6,7,8,9,10] children = [] for i in range(len(nodes)): leftNode = None rightNode = None if i*2 + 1 < len(nodes): leftNode = nodes[i*2 + 1] if i*2 + 2 < len(nodes): rightNode = nodes[i*2 + 2] children.append((leftNode,rightNode)) return children
Wenn das Element, an dem Sie arbeiten, ein Objekt ist, können Sie natürlich einfach eine get-children-Methode aufrufen. Aber ja, Sie brauchen den Index nur dann wirklich, wenn Sie irgendeine Art von Manipulation durchführen.
quelle
Ich habe einen Anwendungsfall, von dem ich glaube, dass keines Ihrer Beispiele ihn abdeckt.
boxes = [b1, b2, b3] items = [i1, i2, i3, i4, i5] for j in range(len(boxes)): boxes[j].putitemin(items[j])
Ich bin relativ neu in Python, obwohl ich so glücklich bin, einen eleganteren Ansatz zu lernen.
quelle
[a - b for a, b in zip(list1, list2)]
ist so viel schöner als[list1[i] - list2[i] for i in range(len(list1))]
... Danke!Wenn Sie die ersten
len(a)
Elemente eines Objekts durchlaufen müssenb
(das ist größer alsa
), sollten Sie wahrscheinlich Folgendes verwendenrange(len(a))
:for i in range(len(a)): do_something_with(b[i])
quelle
for b_elem in b[:len(a)]:...
itertools.islice
.Manchmal interessiert Sie die Sammlung selbst wirklich nicht . Erstellen Sie beispielsweise eine einfache Modellanpassungslinie, um eine "Annäherung" mit den Rohdaten zu vergleichen:
fib_raw = [1, 1, 2, 3, 5, 8, 13, 21] # Fibonacci numbers phi = (1 + sqrt(5)) / 2 phi2 = (1 - sqrt(5)) / 2 def fib_approx(n): return (phi**n - phi2**n) / sqrt(5) x = range(len(data)) y = [fib_approx(n) for n in x] # Now plot to compare fib_raw and y # Compare error, etc
In diesem Fall waren die Werte der Fibonacci-Sequenz selbst irrelevant. Wir brauchten hier nur die Größe der Eingabesequenz, mit der wir verglichen haben.
quelle
Sehr einfaches Beispiel:
def loadById(self, id): if id in range(len(self.itemList)): self.load(self.itemList[id])
Ich kann mir keine Lösung vorstellen, bei der die Range-Len-Zusammensetzung nicht schnell verwendet wird.
Aber wahrscheinlich sollte dies stattdessen getan werden
try .. except
, um pythonisch zu bleiben, denke ich.quelle
if id < len(self.itemList)
Isttry...except
aber besser, wie du sagst.Mein Code lautet:
s=["9"]*int(input()) for I in range(len(s)): while not set(s[I])<=set('01'):s[i]=input(i) print(bin(sum([int(x,2)for x in s]))[2:])
Es ist ein binärer Addierer, aber ich denke nicht, dass der Bereich len oder das Innere ersetzt werden kann, um ihn kleiner / besser zu machen.
quelle