Was ist der Zweck in Python-itertools.wiederholen Sie?
Jedem Gebrauch ich denken kann, für Python itertools.wiederholen()
Klasse, ich kann mir denken, anderen ebenso (vielleicht mehr) akzeptable Lösung zu erzielen den gleichen Effekt. Zum Beispiel:
>>> [i for i in itertools.repeat('example', 5)]
['example', 'example', 'example', 'example', 'example']
>>> ['example'] * 5
['example', 'example', 'example', 'example', 'example']
>>> list(map(str.upper, itertools.repeat('example', 5)))
['EXAMPLE', 'EXAMPLE', 'EXAMPLE', 'EXAMPLE', 'EXAMPLE']
>>> ['example'.upper()] * 5
['EXAMPLE', 'EXAMPLE', 'EXAMPLE', 'EXAMPLE', 'EXAMPLE']
Gibt es irgendeinen Fall, in dem es die am besten geeignete Lösung? Wenn ja, unter welchen Umständen?
- Ich habe eine neue Antwort, die zeigt, dass die ursprüngliche Motivation Anwendungsfall für itertools wiederholen. Auch ich habe soeben die Python docs zu reflektieren, Nutzungs-Hinweis.
- 3 4 code-Beispiele, die nicht wirklich funktionieren. Der erste erzeugt ein generator-Ausdruck, nicht eine
tuple
(Sie möchtentuple(itertools.repeat('example', 5))
), die zweite multipliziert'example'
selbst zu machen'exampleexampleexampleexampleexample'
weil('example')
nichttuple
in den ersten Platz (Sie müssen('example',) * 5
), und Ihre Dritte Beispiel verwendetmap
, was wieder einemap
Objekt, da Python 3map
faul ist (man müsste wickeln Sie es inlist
zu Holen Sie sich die bereitgestellten Ergebnis). Es ist eine interessante Frage, aber faken Ihren code-samples weh tut es. - Ich war ziemlich neu bei Python, wenn ich diesen Beitrag und ich habe einfach schnell getippt, einige Beispiele ohne Prüfung der tatsächlichen Ausgabe. Ein wenig kleinlich, aber ich habe es jetzt behoben, trotzdem. Danke! 🙂
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den
itertools.repeat
Funktion ist faul; es nutzt nur den Speicher für ein Element. Auf der anderen Seite, die(a,) * n
und[a] * n
Idiome erstellen von n Kopien des Objekts im Speicher. Für die fünf Elemente, die Multiplikation idiom ist wahrscheinlich besser, aber bemerken Sie möglicherweise eine Ressource problem, wenn Sie hatte, etwas zu wiederholen, sagen wir, eine million mal.Immer noch, es ist schwer vorstellbar, dass viele statische verwendet für
itertools.repeat
. Die Tatsache jedoch, dassitertools.repeat
ist ein Funktion ermöglicht es Ihnen, in viele funktionelle Anwendungen. Zum Beispiel, haben Sie vielleicht ein paar library-Funktionfunc
die arbeitet auf einer wiederholenden input. Manchmal müssen Sie möglicherweise pre-constructed-Listen der verschiedenen Elemente. Andere Zeiten, können Sie wollen einfach nur operieren auf einer einheitlichen Liste. Wenn die Liste groß ist,itertools.repeat
sparen Sie Speicher.Schließlich
repeat
möglich macht, die sogenannte "iterator-algebra" beschrieben, in deritertools
Dokumentation. Auch dieitertools
Modul selbst verwendet denrepeat
Funktion. Zum Beispiel, der folgende code ist gegeben als eine gleichwertige Umsetzung vonitertools.izip_longest
(obwohl der code der ist wohl in C geschrieben). Beachten Sie die Verwendung vonrepeat
sieben Linien von unten:[a] * n
nicht erstellen n Kopien von a in den Speicher. Es erzeugt n Verweise auf eine einzige Kopie einer. In einigen Fällen ist der Unterschied kann erheblich sein; versuchena = [[]] * 5; a[0].append(1)
.Ist der primäre Zweck der itertools.wiederholen Sie zu liefern, ist ein Strom der Konstanten Werte verwendet werden, die mit Karte oder zip:
Der sekundäre Zweck ist, dass es gibt einen sehr schnellen Weg um die Schleife eine Feste Anzahl von Zeiten wie diesen:
Dies ist schneller als:
Dem ehemaligen gewinnt, weil alle es tun muss ist, aktualisieren Sie die Referenz-Zählung für die bestehenden Keine Objekt. Letztere verliert, weil die Bereich() oder xrange() muss die Herstellung von 10.000 unterschiedliche integer-Objekte.
Hinweis, Guido selbst verwendet, die schnelle looping-Technik in der timeit() Modul. Siehe die Quelle bei https://hg.python.org/cpython/file/2.7/Lib/timeit.py#l195 :
repeat
ist ein Schatz. Warum ist dieses versteckt initertools
und nicht einen integrierten?for _ in range(x): do()
ist wie ein gemeinsames Muster.Ihrem Beispiel zu
foo * 5
sieht oberflächlich ähnlichitertools.repeat(foo, 5)
, aber es ist eigentlich ganz anders.Wenn Sie schreiben
foo * 100000
der interpreter erstellen müssen 100.000 Exemplarenfoo
bevor er Ihnen eine Antwort geben. Es ist also eine sehr teure und Speicher-unfreundliche Bedienung.Aber wenn Sie schreiben
itertools.repeat(foo, 100000)
, der Dolmetscher kann sich wieder ein iterator, dient die gleiche Funktion haben, und nicht brauchen, um zu berechnen, ein Resultat, bis Sie es brauchen-sagen, indem Sie Sie in eine Funktion, die wissen will jedes Ergebnis in der Reihenfolge.Das ist der große Vorteil von Iteratoren: Sie können aufschieben der Berechnung der ein Teil (oder alle) aus einer Liste, bis Sie wirklich brauchen, ist die Antwort.
for i in range(100000):
und dann auffoo
innerhalb der Schleife anstatt zu Fragen, diese Funktion, was Wert, den Sie ihm gegeben?range
ist ein Iteratoren in Python 3, aber in Python 2 gibt es eine Liste. In Python 2 verwenden Siexrange
für ein iterator; in Python 3 verwenden Sielist(range(...))
für eine Liste.range
und Py2xrange
faul sind, aber Sie sind nicht wirklich Iteratoren selbst. Sie sind iteraGemüse, nicht iteraärzte. Sie sind unveränderliche Sequenzen (leicht verkrüppelt auf Python 2xrange
, aber ziemlich vollständig auf Python 3), nur diejenigen, die berechnen Sie Ihren Inhalt auf verlangen. Es macht einen Unterschied, wenn Sie Durchlaufen das gleiche zweimal;r = range(10)
(xrange
auf Py2), gefolgt vonsum(r)
dannsum(r)
wieder produzieren das gleiche Ergebnis jedes mal, wenn es war ein iterator, der zweite Aufruf erzeugt hätte0
(da der erste Aufruf würde die Abgase iterator).Es ist ein iterator. Große Hinweis hier: es ist in dem itertools-Modul. Aus den Unterlagen, die Sie im Zusammenhang mit:
Also Sie werden nicht immer haben, dass alle Sachen in Erinnerung. Ein Beispiel, wo Sie Sie benutzen wollen, könnte es sein
da dies ermöglicht es Ihnen, eine beliebige Anzahl von
4
s, oder was auch immer Sie benötigen könnten, eine unendliche Liste.while True:
und diex
auf Linie 7 bis4
und es wäre nicht das gleiche, wäre besser lesbar, und wäre etwas schneller. Dies ist der Grund, warum ich Frage mich, ob es hatte keinen Zweck.while True:
wäre langsamer alsfor x in itertools.repeat(4):
, weilTrue
war nicht ein Schlagwort damals, sowhile True:
tatsächlich geladen und es getestet für truthiness auf jeder Schleife, um sicher zu sein, hatte niemand zugewiesen, es (while 1:
war eine wahre bedingungslos unendliche Schleife).repeat
hielt den iterator auf den stack (keine Suche in den built-ins scope) und gespeichert, die funktionieren. Zum Glück, auf Python 3True
undFalse
sind die keywords und diewhile True:
ist wirklich bedingungslos unendliche Schleife an der byte-code-Ebene.Wie bereits erwähnt, funktioniert es auch mit
zip
:Anderes Beispiel:
Ergebnis:
Dies zu tun, ohne zu wiederholen, ich würde mit
len(fruits)
.inventory = {fruit: 0 for fruit in fruits}
ist mehr lesbar, und etwas schneller.dict.fromkeys(fruits, 0)
ist die Schnellste (nicht nur für drei Elemente mit einem Konstanten Wert, aufgrund der etwas höheren fixen overhead, aber wenn die Anzahl der Elemente infruits
erhöht,dict.fromkeys
zieht vor, beginnend um acht items); asymptotisch auf meinem Rechner, läuft es in etwa 2/3 der Zeit derdict
Verständnis für große Eingänge. Wie von 3.6 (mit Garantie bestellen fürdict
s),dict.fromkeys(x)
ist ein wirklich effizienter Weg, um uniquify Eingänge beim Erhalt der Bestellung (im Gegensatz zuset(x)
, verliert der Bestellung angeben).Ich in der Regel verwenden, wiederholen Sie die in Verbindung mit Kette und Zyklus. Hier ist ein Beispiel:
Stellt den ersten 2 Früchte, die als Wert 10, dann wird er durchläuft die Werte 1 und 2 für die übrigen Früchte.