2015-09-08 8 views
10

Die Funktion join() akzeptiert einen iterierbaren Parameter. Allerdings habe ich mich gefragt, warum mit:Python: Iteratoren und `join()` besser verstehen

text = 'asdfqwer' 

dieses:

''.join([c for c in text]) 

ist deutlich schneller als:

''.join(c for c in text) 

Das gleiche geschieht mit langen Strings (d text * 10000000).

Wenn ich den Speicherabdruck beider Ausführungen mit langen Strings beobachte, denke ich, dass beide eine und nur eine Liste von Zeichen im Speicher erstellen und sie dann zu einer Zeichenfolge verbinden. Ich vermute also, der Unterschied liegt nur zwischen join() erstellt diese Liste aus dem Generator und wie der Python-Interpreter das gleiche tut, wenn es [c for c in text] sieht. Aber auch hier rate ich nur, also möchte ich, dass jemand meine Vermutungen bestätigt/leugnet.

+0

@AvinashRaj: Wo sehen Sie ein Tupel hier? – Matthias

+0

@Matthias ya, fälschlicherweise als Tupel statt Generator erwähnt. –

+0

Vermutlich beziehen Sie sich auf: http://Stackoverflow.com/a/9061024/3001761 – jonrsharpe

Antwort

10

Die Methode join liest ihre Eingabe zweimal; einmal, um zu bestimmen, wie viel Speicher für das resultierende String-Objekt zugewiesen werden soll, und dann erneut, um den tatsächlichen Join durchzuführen. Das Übergeben einer Liste ist schneller als das Übergeben eines Generatorobjekts, von dem es eine Kopie erstellen muss, damit es zweimal durchlaufen werden kann.

Ein Listenverständnis ist nicht einfach ein Generatorobjekt, das in eine Liste eingepackt ist. Daher ist es schneller, die Liste extern zu erstellen, als join aus einem Generatorobjekt erstellen zu lassen. Generatorobjekte sind für die Speichereffizienz und nicht für die Geschwindigkeit optimiert.

Natürlich ist ein String bereits ein iterables Objekt, so dass Sie einfach ''.join(text) schreiben könnten. (Auch dies ist nicht so schnell wie das Erstellen der Liste explizit aus der Zeichenfolge.)

+0

Ich habe das gerade mit einem Generator getestet, der druckt. 'Join' hat den Generator nicht zweimal ausgeführt. Es ist eine ziemlich weit hergeholte Behauptung. Was lässt Sie glauben, dass der Generator zweimal ausgeführt wird? –

+1

@DanielDarabos * "dass es eine Kopie von" * erstellen muss - indem es in eine Liste aufgenommen wird! – jonrsharpe

+2

Hier meinen Fragekommentar reproduzieren, da Sie es in Ihrer Antwort erwähnt haben: Interessanterweise zeigt "Zeit" auf meinem System, dass eine Liste auch hier schneller ist als die direkte Stringiteration. –